PostgreSQLで0列の扱い
きっかけ
現在のバージョンのPostgreSQLではSELECT ;というSQL文を実行してもエラーになりません。
試してみると(1 row)と返ってきたので、あれ?なんで?となりました。
これは、列数が0なんですね。PostgreSQLは列数が0のテーブルが作れるので、それに合わせているようです。
— Tatsuo Ishii (@tatsuo_ishii) July 13, 2022
CREATE empty();
列数が0という指摘を受けて、一応0列があることを理解していたつもりだったのですけど、 その仕様を勘違いしていたことに気づきました。
テーブルを省略したSELECTの扱い
全部のSQL実装では無いですが、SQLのSELECTはFROM句がなくても動作する実装が多いです。
psqlで実行すると以下のようになります。
のようにすれば文字列1が返ってきます。列名は無いので?column?で表されていますが、1行1列のテーブルと同じ扱いになります。
SELECT ;はこの流れで行数が1で、列数が0のテーブルということになります。
psqlでは実行すると以下のように行が(改行も含めて)表示されないまま 1 row と表示されるのでちょっと変な感じがしたのですが、これはpsql側でどう表示するかの問題であって、1行0列のテーブルと同じ扱いになっています。
なにも指定していないので、0行0列になるかと勘違いしてましたが、1行0列の方が正しいとわかります。
PostgreSQLは0列のテーブルが作れる
前述の石井さんから指摘にあるように最近のPostgreSQLでは0列のテーブルが作成できるようになっています。
元からSQLでは行をINSERTしなければ0行のテーブルになるので、0列のテーブルを作っただけだと0列0行のテーブルになります。
psqlの表示では0列の場合(1 row)と(0 rows)の表示でしか区別出来ないですが、0行と1行でちゃんと違いがあって整合が取れている動作になっています。
0列のテーブル操作
前は0列のSQLが許可されないところが多かったのですが、現在進行形で0列を許可するように修正されているので、前はエラーになったものが通るようになっていたり、これから通るようになったりする可能性があります。
INSERT
0列のテーブルにINSERTしようとすると素直にできませんでした。
SELECT
列数が0のテーブルだけでなく、列数が1つ以上のテーブルであってもSELECT FROM oneで列数が0で返すことができます。
これにより列数が0で、複数行のテーブルを表現できます。
INSERT INTO SELECT
ということはINSERT INTO table SELECTならINSERTが可能になります。
INSERT出来てます。
行数が0のときとは明確に区別されます。
行数0でもSELECT i FROMにしてしまうとちゃんとエラーになります。