web-dev-qa-db-ja.com

TYPEを部分的に初期化する方法はありますか?

カスタムタイプを作成しました。

CREATE TYPE my_type as(name text, street text, location text);

そのような型の初期化は簡単です:

SELECT ROW('a', 'b', 'c')::my_type;

型を部分的に初期化する簡単な方法があるかどうか、つまり、言及されていないすべての列が暗黙的にnullに設定されているかどうか疑問に思っています。疑似コードでは、次のようになります。

SELECT ROW('a', 'c')::my_type(name, location);

さらに、列が正しい順序で言及されていない場合に型を初期化する方法もありますか?疑似コードでは、次のようになります。

SELECT ROW('c', 'a', 'b')::my_type(location, name, street);
6
Katrin

タイプ定義に基づくコード例:

_CREATE TYPE my_type AS (name text, street text, location text);
_

構文は不可能です(すでにご存じのとおり)。 プレーンキャスト は、フィールドの(部分的な)リストを許可しません。

SELECT ROW('a', 'c')::my_type(name, location);

プレーンSQLキャスト式では、欠落しているフィールドにNULL値(またはその他のデフォルト)を指定する必要があります。

_SELECT ROW('a', NULL, 'c')::my_type;
_

または、入力として行型リテラルを使用します。

_SELECT '(a,NULL,c)'::my_type;
_

INSERT または UPDATE ステートメントは、複合タイプのフィールドを個別にターゲットにすることができます。 (基になる型はターゲットから派生します。)デモ:

_CREATE TABLE tbl (tbl_id serial, comp my_type);

INSERT INTO tbl (comp.name, comp.location) VALUES ('a', 'c')

UPDATE tbl
SET    comp.name = 'X'
     , comp.street = 'Y'
WHERE  tbl_id = 1;
_

明示的に入力されていないフィールドは、デフォルトでNULLになります。 (タイプが異なるdefaultでない限り、これは一般的ではありません。)

DELETE の場合は不可能です。これにより、常に行全体が削除されます。論理的には、サブフィールドNULLを設定することになります。

_UPDATE tbl
SET    comp.name = NULL
WHERE  tbl_id = 1;
_

通常、手続き型言語関数で変数を使用します-デフォルトPL/pgSQL。そこに _SELECT INTO_ があります。また、複合タイプのフィールドを個別にアドレス指定できます。デモ:

_DO
$$
DECLARE
    _var my_type;
BEGIN
   SELECT INTO _var.location, _var.name  -- in any chosen order
          'c', 'a';
   RAISE NOTICE '%', _var;
END
$$
_

db <> fiddle ここ

PL/pgSQLの割り当てを_SELECT INTO_およびSQLコマンド_SELECT INTO_と混同しないでください(まったく使用しないでください。代わりに_CREATE TABLE AS_を使用してください)。見る:

関連する、より洗練されたトリック:

5

はい。これは任意のタイプを使用して行うことができます

  1. それはコンストラクタがrecordを取り、マージをサポートします(またはPostgreSQLが「連結する」(||))。この例はhstoreです。

  2. 複合型で、レコードの操作をサポートする任意の型を使用します。思い浮かぶ2つのオプションは、jsonbhstoreです。

jsonb

-- In a single call to jsonb_populate_record
SELECT jsonb_populate_record(
  null::my_type,
  jsonb_build_object('name', 'Evan')
);

-- With a subsequent merge after construction
SELECT jsonb_populate_record(
  null::my_type,
  '{}'
) || jsonb_build_object('name', 'Evan');

hstore

hstoreは、実際にこれを行で直接実行することをサポートしています。

-- With single-call methods to #= or populate_record
CREATE EXTENSION hstore;
SELECT null::my_type #= hstore('name', 'Evan');
SELECT populate_record(null::my_type, hstore('name', 'Evan'))

最初のオプションは次のようになります。

-- With a subsequent merge after construction
CREATE EXTENSION hstore;
SELECT hstore(null::my_type) || hstore('name', 'Evan');

こちらもご覧ください

2
Evan Carroll