MW211 EXIT

devlog
PostgreSQL/0を除く最小値(2)
2012年05月30日
ということで、NULLを含む列についての0を除く最小値を求める方法。
┌──────────────────────────────────────┐
│SELECT CASE                                                                 │
│           WHEN MIN(列) IS NULL THEN NULL                                   │
│           ELSE                                                             │
│               COALESCE(MIN(CASE                                            │
│                                WHEN 列 = 0 THEN NULL                       │
│                                ELSE             列                         │
│                            END), 0)                                        │
│       END AS 列                                                            │
│    FROM 表                                                                 │
│    GROUP BY キー                                                           │
└──────────────────────────────────────┘
ちと条件分岐が強引か。。。

すべてNULLならNULL、1以上を一つでも含んでいればその最小値、
さもなくば0となる。(なんか初心者のような条件分岐の説明だなぁ)

とにかくやりたいことは満たせるはず。

ちなみに、すべてNULLを判定する式は一般的にはCOUNT()を使うのが自然かも。
┌──────────────────────────────────────┐
│SELECT CASE                                                                 │
│           WHEN COUNT(列) = 0 THEN NULL                                     │
│           ELSE                                                             │
│               COALESCE(MIN(CASE                                            │
│                                WHEN 列 = 0 THEN NULL                       │
│                                ELSE             列                         │
│                            END), 0)                                        │
│       END AS 列                                                            │
│    FROM 表                                                                 │
│    GROUP BY キー                                                           │
└──────────────────────────────────────┘
ま、意図するところを伝えるのなら前出のMIN()の方がわかりやすいかな。
分類:PostgreSQL
PostgreSQL/0を除く最小値(1)
2012年05月29日
0を除く最小値を求める方法。
┌──────────────────────────────────────┐
│SELECT COALESCE(MIN(CASE                                                    │
│                        WHEN 列 = 0 THEN NULL                               │
│                        ELSE             列                                 │
│                    END), 0) AS 列                                          │
│    FROM 表                                                                 │
│    GROUP BY キー                                                           │
└──────────────────────────────────────┘
ただし、NOT NULL制約の列にしか使えない。。。
分類:PostgreSQL
PostgreSQL/関数実行
2012年05月27日
pgAdminとかでSQL文を発行して関数を実行する方法
┌──────────────────────────────────────┐
│SELECT 関数();                                                              │
└──────────────────────────────────────┘
え?SELECT?
分類:PostgreSQL
PostgreSQL/地域の設定
2012年05月21日
「CREATE DATABASE」を行う時、以下を指定することにより地域を設定できる。
┌──────┬─────────┐
│LC_COLLATE  │並替順            │
├──────┼─────────┤
│LC_CTYPE    │大文字小文字の区別│
├──────┼─────────┤
│LC_MESSAGES │メッセージ        │
├──────┼─────────┤
│LC_MONETARY │通貨書式          │
├──────┼─────────┤
│LC_NUMERIC  │数字書式          │
├──────┼─────────┤
│LC_TIME     │日時書式          │
└──────┴─────────┘
「C」を設定すると、地域を設定しないのと同等になる。

「ja」(日本語)とかを設定すると、並替など、
その言語(日本語)に特化した機能となるが、その分遅かったり、
他言語には影響がなかったりする。

とりあえず「C」(設定なし)としておく方が無難か。
分類:PostgreSQL
PostgreSQL/シーケンス
2012年04月13日
serial型とかの自動でインクリメントしてれるIDがあった場合、
「表」に対して「表のシーケンス」的なものが自動で生成される。

「表のシーケンス」と「表」は同期を合わせなければならないので、
「表」を空っぽにしたら、以下のように「表のシーケンス」も
初期値に戻さなければならない。
┌──────────────────────────────────────┐
│SELECT SETVAL ('表のシーケンス', 1, false);                                 │
└──────────────────────────────────────┘
#第三パラメータに「false」を指定すると、「1」の手前、つまり「0」が設定される

その後、INSER文をそのシーケンス項目以外に実行してあげれば、
シーケンス項目は自動でインクリメントしてくれる。
┌──────────────────────────────────────┐
│INSERT INTO 表 (列) VALUES ('値');                                          │
│INSERT INTO 表 (列) VALUES ('値');                                          │
│INSERT INTO 表 (列) VALUES ('値');                                          │
└──────────────────────────────────────┘
この場合「1,2,3」が割り振られ、
「表のシーケンス」は「3」となり次回は「4」が割り振られる。

しかし、そのシーケンスを任意の値に指定した場合は、
シーケンスはインクリメントされない。
┌──────────────────────────────────────┐
│INSERT INTO 表 (id, 列) VALUES (1, '値');                                   │
│INSERT INTO 表 (id, 列) VALUES (2, '値');                                   │
│INSERT INTO 表 (id, 列) VALUES (3, '値');                                   │
└──────────────────────────────────────┘
「id」がシーケンス項目にあたるとした場合、自動インクリメントされないので
「表のシーケンス」は「0」のままだ。

┌──────────────────────────────────────┐
│INSERT INTO 表 (列) VALUES ('値');                                          │
└──────────────────────────────────────┘
これで「id」が一意キーであったとして、
次に上記のような「id」を指定しないINSERTをしたら
「id」に「1」が設定されるので、二重キーエラーとなってしまう。

ここは「表のシーケンス」を「3」にする必要がある。

それには、こうだ。
┌──────────────────────────────────────┐
│SELECT SETVAL('表のシーケンス', 3, true);                                   │
└──────────────────────────────────────┘

「pgAdmin」で、INSERT文形式でエクスポート(バックアップ)した時に、
何気に付随しているので要注目だ。
分類:PostgreSQL
PostgreSQL/9.0と9.1の違い(2)
2012年04月06日
PostgreSQLの9.0と9.1では「standard_conforming_strings」の既定値が変更になった。
┌────┬─────────────────┐
│9.0以前 │standard_conforming_strings = off │
├────┼─────────────────┤
│9.1以降 │standard_conforming_strings = on  │
└────┴─────────────────┘

比較すると、こんな感じ。
┌────────┬───────┬───────┬───────┐
│                │ E''で囲った  │ 9.0以前(off) │ 9.1以降(on)  │
├────────┼───────┼───────┼───────┤
│特殊文字「\d」  │E'\\d'        │'\\d'         │'\d'          │
├────────┼───────┼───────┼───────┤
│「\」の一致     │= E'\\'       │= '\\'        │= '\'         │
├────────┼───────┼───────┼───────┤
│「\」のLIKE一致 │LIKE E'%\\\\%'│LIKE '%\\\\%' │LIKE '%\\%'   │
└────────┴───────┴───────┴───────┘

これまでは、常時「正規表現ですよ」という臨戦態勢だったのが、
これからは、「E''」で囲った時だけ特別に「正規表現ですよ」という風になった。

なお、PDOではこの設定値をみて、差異を吸収してくれるので
「standard_conforming_strings = on」状態のような感じで
値を指定してあげれば(「\」とかおおめに指定しなくてもよい、これまでもそう)、
よろしくやってくれる。
分類:PostgreSQL
PostgreSQL/9.0と9.1の違い(1)
2012年04月05日
PostgreSQLの9.0と9.1では「standard_conforming_strings」の既定値が変更になった。
┌────┬─────────────────┐
│9.0以前 │standard_conforming_strings = off │
├────┼─────────────────┤
│9.1以降 │standard_conforming_strings = on  │
└────┴─────────────────┘

エスケープ文字の扱いは以下のように違う。
┌──┬───┬───┬───┬───┐
│    │'     │"     │\     │\     │
├──┼───┼───┼───┼───┤
│off │'\''  │'"'   │'\\'  │E'\\' │
├──┼───┼───┼───┼───┤
│on  │''''  │'"'   │'\'   │E'\\' │
└──┴───┴───┴───┴───┘

よって、サニタイズの仕方も以下のように違ってくる。
┌───────┬───────┐
│ 9.0以前(off) │ 9.1以降(on)  │
├───────┼───────┤
│「'」→「\'」 │「'」→「''」 │
├───────┼───────┤
│「"」→「\"」 │  (そのまま)  │
├───────┼───────┤
│「\」→「\\」 │              │
└───────┴───────┘
分類:PostgreSQL
PostgreSQL/順番の末尾にデータを追加したい場合
2011年10月23日
順番を示す項目について、データを追加する場合に
その時点で存在するデータの最大値に+1して追加したい場合、
以下のようにSELECTで最大値をひっぱてきて、それに+1してINSERTする。
┌──────────────────────────────────────┐
│INSERT INTO "表"                                                            │
│           ("名前","順番")                                                  │
│    SELECT '文字',                                                          │
│           MAX("順番") + 1                                                  │
│        FROM "表";                                                          │
└──────────────────────────────────────┘
しかし、これだと最初に追加する場合、エラーになってしまう(データが追加できない)。
つまり、順番を示す項目の最大値が該当なしでNULLとなってしまい、+1できないのだ。

そこで、ひと手間。
以下のようにNULLの場合に0に変換する「COALESCE()」をはさんであげるとよい。
#COALESCE()は引数(配列)中のNULLじゃない最初のデータを採用する関数
┌──────────────────────────────────────┐
│INSERT INTO "表"                                                            │
│           ("名前","順番")                                                  │
│    SELECT '文字',                                                          │
│           COALESCE(MAX("順番"), 0) + 1                                     │
│        FROM "表";                                                          │
└──────────────────────────────────────┘
ちなみに、SELECTは()で括れば個別に引用できるので、以下のようにもできる。
┌──────────────────────────────────────┐
│INSERT INTO "表"                                                            │
│           ("名前","順番")                                                  │
│    VALUES ('文字',                                                         │
│            COALESCE((SELECT MAX("順番")                                    │
│                          FROM "表";                                        │
│                     ), 0) + 1;                                             │
└──────────────────────────────────────┘
これだと複数のテーブルから様々な項目を参照できる。
分類:PostgreSQL
PostgreSQL/数値文字変換
2011年09月26日
本来数値である項目を事情があって文字型項目として保持してたりして
これを本来の数値型に変換して取得したい場合には、「TO_NUMBER()」を使う。
┌──────────────────────────────────────┐
│TO_NUMBER(列,'S999D0')                                                      │
└──────────────────────────────────────┘
こんな感じになる。
第二引数として、書式を指定してやるのがちょっとめんどくさいかも。

一方その反対に数値を文字型に変換するのは「TO_CHAR()」だ。
┌──────────────────────────────────────┐
│TO_CHAR(列,'S999D0')                                                        │
└──────────────────────────────────────┘
こんな感じ(TO_NUMBER()と同じ)。
日付型なんかは以下のような感じで変換できて便利。
┌──────────────────────────────────────┐
│TO_CHAR(列,'YYYY-MM-DD HH24:MI:SS')                                         │
└──────────────────────────────────────┘
さて、話は戻って「TO_NUMBER()」。
こいつが意外と厄介で、入力値(つまり参照する列)に文字列が混じっていると
エラーとなってしまうのである(NULLならOK、''はNG)。

そこで、ISNUMERIC的なことをして条件分岐させたいところだが、見当たらない。
ならばということで、正規表現で数値を抜き出す方法を代案として考えた。
┌──────────────────────────────────────┐
│SUBSTRING(列 FROM E'^\-*[0-9]+\.?[0-9]*$')                                  │
└──────────────────────────────────────┘
これならエラーを回避できる。
┌──────────────────────────────────────┐
│TO_NUMBER(SUBSTRING(列 FROM E'^\-*[0-9]+\.?[0-9]*$'),'S999D0')              │
└──────────────────────────────────────┘
文字列が混じっている場合は、NULLになる。
分類:PostgreSQL
PostgreSQL/boolean型
2011年09月15日
PostreSQLにおいてboolean型の項目の値は、
普通にSQL文を実行したり、pg_query()を使ったりすると
「t」(true)か「f」(false)という一文字で取得される。
なので、取得された結果を使う場合、
「if(■ == 't')」とかって判定をしなきゃならない。

でも、PDO(->execute()したり、->fetch()したり)だと
「1」(true)か「」(false)という形で取得される。
つまりこれだと「if(■)」でOKだ。

追記:PHPで「echo TRUE;」ってすると「1」が表示される。
上記の「1」は「=== TRUE」では真だが「=== 1」や「=== '1'」では偽だ。
まぎれもなく、「TRUE」のようだ。

ちなみに、SQL文中のSELECTのWHERE句、INSERTのVALUES句、UPDATEのSET句とかでは
「true」「false」をそのまま使える。
あくまで参照結果の話。

追記:以下でも入力可能みたい
・trueなら「TRUE」「't'」「'true'」「'y'」「'yes'」「'1'」
・falseなら「FALSE」「'f'」「'false'」「'n'」「'no'」「'0'」
分類:PHP、PostgreSQL
前へ 1 2 3 4 5 6 7 8 9 10 11 次へ