PostgreSQLは、MS SQL Serverのように計算/計算された列をサポートしていますか?ドキュメントには何も見つかりませんが、この機能は他の多くのDBMSに含まれているため、何か不足している可能性があると思いました。
PostgreSQLは、MS SQL Serverのように計算/計算された列をサポートしていますか?ドキュメントには何も見つかりませんが、この機能は他の多くのDBMSに含まれているため、何か不足している可能性があると思いました。
回答:
SQL標準で定義され、DB2、MySQL、Oracleを含む一部のRDBMSで実装されているように、Postgres 11まで生成された列はサポートされていません。SQL Server の同様の「計算列」も同様です。
STORED
生成されたカラムはPostgres 12で導入されました。簡単な例:
CREATE TABLE tbl (
int1 int
, int2 int
, product bigint GENERATED ALWAYS AS (int1 * int2) STORED
);
ここに db <> fiddle
VIRTUAL
生成された列には、次の反復の1つが含まれる場合があります。(まだPostgres 13にはありません)。
関連:
それまでは、仮想生成列と同じように機能する属性表記()を使用VIRTUAL
する関数を使用して、生成列をエミュレートできます。これは、歴史的な理由でPostgresに存在する構文の奇妙な点であり、たまたまケースに当てはまります。この関連する回答にはコード例があります:tbl.col
SELECT * FROM tbl
ただし、式(列のように見える)はに含まれていません。常に明示的にリストする必要があります。
関数が提供されている場合、一致する式のインデックスでサポートすることもできますIMMUTABLE
。お気に入り:
CREATE FUNCTION col(tbl) ... AS ... -- your computed expression here
CREATE INDEX ON tbl(col(tbl));
または、同様にVIEW
、オプションで式インデックスと組み合わせて、同様の機能を実装できます。次にSELECT *
、生成された列を含めることができます。
「持続」(STORED
)計算列は、機能的に同じ方法でトリガーを使用して実装できます。
マテリアライズドビューは、Postgres 9.3以降に実装された密接に関連する概念です。
以前のバージョンでは、MVを手動で管理できました。
はい、できます! ソリューションは簡単、安全、そして高性能でなければなりません...
私はpostgresqlを使い始めたばかりですが、ビューと組み合わせて式インデックスを使用して計算列を作成できるようです(ビューはオプションですが、作業が少し楽になります)。
私の計算がmd5(some_string_field)
であるとすると、次のようにインデックスを作成します。
CREATE INDEX some_string_field_md5_index ON some_table(MD5(some_string_field));
これで、作用するクエリはすべてMD5(some_string_field)
、最初から計算するのではなく、インデックスを使用します。例えば:
SELECT MAX(some_field) FROM some_table GROUP BY MD5(some_string_field);
ただし、この時点では、列の構築方法を正確に知っているテーブルのユーザーに依存しています。簡単にするためVIEW
に、元のテーブルの拡張バージョンにを作成し、計算値を新しい列として追加できます。
CREATE VIEW some_table_augmented AS
SELECT *, MD5(some_string_field) as some_string_field_md5 from some_table;
これで、を使用some_table_augmented
するすべてのクエリはsome_string_field_md5
、それがどのように機能するかを心配することなく使用できます。ビューは元のテーブルからデータをコピーしないため、パフォーマンスとメモリの両方で優れています。ただし、ソーステーブルにのみビューを更新または挿入することはできませんが、本当に必要な場合は、ルールを使用してソーステーブルに挿入と更新をリダイレクトできると思います(最後の点で間違っている可能性があります)自分で試したことがありません)。
編集:クエリに競合するインデックスが含まれる場合、プランナーエンジンが式インデックスをまったく使用しない場合があります。選択はデータに依存するようです。
if the query involves competing indices
か?
これを行う1つの方法は、トリガーを使用することです。
CREATE TABLE computed(
one SERIAL,
two INT NOT NULL
);
CREATE OR REPLACE FUNCTION computed_two_trg()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $BODY$
BEGIN
NEW.two = NEW.one * 2;
RETURN NEW;
END
$BODY$;
CREATE TRIGGER computed_500
BEFORE INSERT OR UPDATE
ON computed
FOR EACH ROW
EXECUTE PROCEDURE computed_two_trg();
トリガーは、行が更新または挿入される前に発生します。NEW
レコードを計算するフィールドを変更し、そのレコードを返します。
insert into computed values(1, 2); insert into computed values(4, 8); commit; select * from computed;
:戻り値は:1 2および4 8
insert into computed(one) values(1); insert into computed(one) values(4); commit; select * from computed;
の値を試してみてくださいtwo
自動的に計算されます!
PostgreSQL 12は生成された列をサポートします:
PostgreSQL 12 Beta 1がリリースされました!
生成された列
PostgreSQL 12では、他の列の内容を使用する式で値を計算する生成された列を作成できます。この機能は、挿入および更新時に計算され、ディスクに保存される、格納された生成列を提供します。クエリの一部として列が読み取られるときにのみ計算される仮想生成列は、まだ実装されていません。
生成された列は、常に他の列から計算される特別な列です。したがって、ビューはテーブルと同じです。
CREATE TABLE people (
...,
height_cm numeric,
height_in numeric GENERATED ALWAYS AS (height_cm * 2.54) STORED
);
機能し、計算された用語を使用するコードがあります。PADBで実行する純粋なpostgresSQLではありません。
使い方はこちら
create table some_table as
select category,
txn_type,
indiv_id,
accum_trip_flag,
max(first_true_origin) as true_origin,
max(first_true_dest ) as true_destination,
max(id) as id,
count(id) as tkts_cnt,
(case when calculated tkts_cnt=1 then 1 else 0 end) as one_way
from some_rando_table
group by 1,2,3,4 ;
チェック制約付きの軽量ソリューション:
CREATE TABLE example (
discriminator INTEGER DEFAULT 0 NOT NULL CHECK (discriminator = 0)
);
field as 1 persisted
。