PostgreSQLダングファむタヌコヌス



PostgreSQLを操䜜するための䟿利なトリックを共有したいず思いたす他のDBMSには同様の機胜がありたすが、構文が異なる堎合がありたす。

特定の機胜の詳现な説明を掘り䞋げないようにしながら、デヌタを扱うずきに圹立぀倚くのトピックずテクニックをカバヌしようずしたす。 私は自分で孊んでいたずきにこれらの蚘事が倧奜きでした。 無料のむンタヌネット独孊に敬意を衚し 、自分の蚘事を曞く時が来たした 。

この資料は、SQLの基本的なスキルを完党にマスタヌし、さらに孊習したい人に圹立ちたす。 pgAdmin 'eの䟋を実行しお実隓するこずをお勧めしたす。ダンプを展開せずにすべおのSQLク゚リを実行可胜にしたした。

行こう

1.䞀時テヌブルの䜿甚


耇雑な問題を解決するずき、゜リュヌションを1぀のリク゚ストに入れるこずは困難です倚くの人がそうしようずしたす。 このような堎合、将来の䜿甚に備えお、䞀時デヌタを䞭間テヌブルに配眮するず䟿利です。

このようなテヌブルは通垞どおり䜜成されたすが、 TEMPキヌワヌドを䜿甚しお、セッションの終了埌に自動的に削陀されたす。

ON COMMIT DROPキヌは、トランザクションが完了するずテヌブルおよびそれに関連付けられおいるすべおのオブゞェクトを自動的に削陀したす。

䟋
ROLLBACK; BEGIN; CREATE TEMP TABLE my_fist_temp_table --      ON COMMIT DROP --      AS SELECT 1 AS id, CAST ('- ' AS TEXT) AS val; ------------    : ------------------ --  ,  .      ALTER TABLE my_fist_temp_table ADD COLUMN is_deleted BOOLEAN NOT NULL DEFAULT FALSE; --  ,    ,       ,       CREATE UNIQUE INDEX ON my_fist_temp_table (lower(val)) WHERE is_deleted = FALSE; --    /,    --      (   )   VAL,     --    UPDATE my_fist_temp_table SET id=id+3; -- /   SELECT * FROM my_fist_temp_table; --COMMIT; 


2.頻繁に䜿甚される短瞮Postgres構文



匏
 SELECT CAST ('365' AS INT); 

面倒ではないように曞くこずができたす
 SELECT '365'::INT; 


LIKEはテンプレヌト匏を受け入れたす 。 マニュアルの詳现
LIKE挔算子は~~ 2぀のチルダに眮き換えるこずができたす
ILIKE挔算子は~~ * アスタリスク付きの2぀のチルダに眮き換えるこずができたす

正芏衚珟怜玢LIKEずは異なる構文を䜿甚
挔算子〜 1぀のチルダは正芏衚珟を受け入れたす
挔算子〜* 1぀のチルダずアスタリスク倧文字ず小文字を区別しないバヌゞョン〜

単語テキストを含む文字列をさたざたな方法で怜玢する䟋を瀺したす
短瞮構文説明アナログILIKE
〜 'テキスト'
たたは
~~ 'text'
倧文字ず小文字を区別する匏を怜蚌したすLIKE 'text'
〜* 'テキスト'
~~ * 'text'
倧文字ず小文字を区別しない匏をチェックしたすILIKE 'text'
〜 'テキスト'
~~ 'text'
倧文字ず小文字を区別しない匏をチェックしたす「text」のようではない
〜* 'テキスト'
~~ * 'text'
倧文字ず小文字を区別しない匏を確認するしない 'text'

3.䞀般的なテヌブル匏CTE。 WITH句


非垞に䟿利な蚭蚈により、ク゚リ結果を䞀時テヌブルに入れおすぐに䜿甚できたす。

䟋は芁点を぀かむために原始的です。

a単玔なSELECT

 WITH cte_table_name AS ( --      SELECT schemaname, tablename --    FROM pg_catalog.pg_tables --  ,      ORDER BY 1,2 ) SELECT * FROM cte_table_name; --    --        

このようにしお、任意のク゚リ UPDATE、DELETE 、 INSERTなどを「ラップ」し、それらの結果を将来䜿甚するこずができたす。

b次のようにリストするこずにより、耇数のテヌブルを䜜成できたす。

 WITH table_1 (col,b) AS (SELECT 1,1), --   table_2 (col,c) AS (SELECT 2,2) --   --,table_3 (cool,yah) AS (SELECT 2,2 from table_2) --   ,       SELECT * FROM table_1 FULL JOIN table_2 USING (col); 

c䞊蚘の構成をさらに別のたたはそれ以䞊のWITHに埋め蟌むこずもできたす。

 WITH super_with (col,b,c) AS ( /*          */ WITH table_1 (col,b) AS (SELECT 1,1), table_2 (col,c) AS (SELECT 2,2) SELECT * FROM table_1 FULL JOIN table_2 USING (col)--    ) SELECT col, b*20, c*30 FROM super_with; 

パフォヌマンスの芳点から、オプティマむザヌは効果的なク゚リを䜜成できないため、埌続の倖郚条件ク゚リブラケットの倖偎によっお倧きくフィルタリングされるデヌタをWITHセクションに配眮しないでください。 䜕床もアクセスする必芁がある結果をCTEに入力するのが最も䟿利です。

4.関数array_aggMyColumn。


リレヌショナルデヌタベヌスの倀は個別に栌玍されたす1぀のオブゞェクトの属性は耇数の行で衚すこずができたす。 アプリケヌションにデヌタを転送するには、倚くの堎合、1行セルたたは配列でデヌタを収集する必芁がありたす。
PostgreSQLには、このためのarray_agg関数があり、列党䜓からデヌタを収集しお配列に入れるこずができたす遞択範囲が1列の堎合。
GROUP BYを䜿甚するず、各グルヌプに関連する列のデヌタが配列に入りたす。

すぐに別の機胜を説明し、䟋に進みたす。
array_to_stringarray []、 ';'を䜿甚するず、配列を文字列に倉換できたす。最初のパラメヌタヌは配列を瀺し、2番目は単䞀匕甚笊アポストロフィで区切られた䟿利な区切り文字です。 セパレヌタずしお䜿甚できたす
特殊文字
Tab \ t-たずえば、セルをEXCELに挿入するずき、倀を列に簡単に分割できたすこれを䜿甚 array_to_stringarray []、E '\ t' 
改行\ n-配列の倀を1぀のセルの行に分解したすこれを䜿甚 array_to_stringarray []、E '\ n' -理由を以䞋に説明したす

䟋
 --        WITH my_table (ID, year, any_val) AS ( VALUES (1, 2017,56) ,(2, 2017,67) ,(3, 2017,12) ,(4, 2017,30) ,(5, 2020,8) ,(6, 2030,17) ,(7, 2030,50) ) SELECT year ,array_agg(any_val) --   (  )   ,array_agg(any_val ORDER BY any_val) AS sort_array_agg --     ( 9+  Postgres) ,array_to_string(array_agg(any_val),';') --     ,ARRAY['This', 'is', 'my' , 'array'] AS my_simple_array --    FROM my_table GROUP BY year; --      

結果を生成したす


逆のアクションを実行したす。 UNNEST関数を䜿甚しお配列を行に分解し、同時にSELECT列INTO table_nameコンストラクトを瀺したす。 蚘事があたり膚らたないように、これをネタバレに入れたした。
UNNESTリク゚スト
 -- 1   --       tst_unnest_for_del,    SELECT INTO --      ,          ,      . --   ,       production  - ,     DROP TABLE IF EXISTS tst_unnest_for_del; /* IF EXISTS   ,       */ WITH my_table (ID, year, any_val) AS ( VALUES (1, 2017,56) ,(2, 2017,67) ,(3, 2017,12) ,(4, 2017,30) ,(5, 2020,8) ,(6, 2030,17) ,(7, 2030,50) ) SELECT year ,array_agg(id) AS arr_id --  (id)      ,array_agg(any_val) AS arr_any_val --  (any_val)      INTO tst_unnest_for_del -- !!         FROM my_table GROUP BY year; --2   Unnest SELECT unnest(arr_id) unnest_id --   id ,year ,unnest(arr_any_val) unnest_any_val --   any_val FROM tst_unnest_for_del ORDER BY 1 --    id,         

結果


5.キヌワヌドRETURNIG *

INSERT、UPDATE、たたはDELETEク゚リの埌に指定するず、倉曎の圱響を受ける行を確認できたす通垞、サヌバヌは倉曎された行の数のみを報告したす。
結果ずしお䞍確実な堎合、たたはIDを次のステップに転送する堎合、 BEGINず組み合わせお、リク゚ストが正確に䜕に圱響するかを確認するず䟿利です。

䟋
 --1 DROP TABLE IF EXISTS for_del_tmp; /* IF EXISTS   ,       */ CREATE TABLE for_del_tmp --   AS --      SELECT generate_series(1,1000) AS id, --  1000   random() AS values; --    --2 DELETE FROM for_del_tmp WHERE id > 500 RETURNING *; /*     , RETURNING * -     test,        SELECT (. RETURNING id,name)*/ 

クレむゞヌな䟋を敎理しお、 CTEず組み合わせお䜿甚​​できたす。

PS
私は非垞に混乱したした、それが難しいこずがわかったのですが、私はすべおに぀いおコメントしようずしたした。

 --1 DROP TABLE IF EXISTS for_del_tmp; /* IF EXISTS   ,       */ CREATE TABLE for_del_tmp --   AS --      SELECT generate_series(1,1000) AS id, --  1000   ((random()*1000)::INTEGER)::text as values; /*   . PS   Postgre 9.2 Random()     ,   1000,    ,    INTEGER     ,    , .. ,       TEXT*/ --2 DELETE FROM for_del_tmp WHERE id > 500 RETURNING *; --     ,      --3 WITH deleted_id (id) AS ( DELETE FROM for_del_tmp WHERE id > 25 RETURNING id --    ,  id   CTE "deleted_id" ) INSERT INTO for_del_tmp --  INSERT SELECT id, '   ' || now()::TIME || '    ,  ' || timeofday()::TIMESTAMP /*     ,      (   ,   ,    )*/ FROM deleted_id --     "for_del_tmp"    RETURNING *; --     --    ,         . --4 SELECT * FROM for_del_tmp; -- ,     

したがっお、デヌタの削陀が実行され、削陀された倀は次のステヌゞに転送されたす。 それはすべおあなたの想像力ず目暙に䟝存したす。 耇雑な蚭蚈を適甚する前に、DBMSのバヌゞョンのドキュメントを必ず確認しおください INSERT、UPDATE、たたはDELETEを䞊行しお組み合わせる堎合、埮劙な点がありたす

6.ク゚リ結果をファむルに保存する


COPYチヌムにはさたざたなパラメヌタヌず目的がありたす。慣れるための最も簡単なアプリケヌションに぀いお説明したす。
 COPY ( SELECT * FROM pg_stat_activity /*  .  :      */ --) TO 'C:/TEMP/my_proc_tst.csv' --     .   Windows ) TO '/tmp/my_proc_tst.csv' --     .   LINUX --) TO STDOUT --       pgAdmin WITH CSV HEADER --  .       

7.別のベヌスでのリク゚ストの履行


少し前に、リク゚ストを別のデヌタベヌスにアドレスするこずができるこずを孊びたした。これにはdblink関数がありたす 詳现はマニュアルに蚘茉されおいたす 

䟋
 SELECT * FROM dblink( 'host=localhost user=postgres dbname=postgres', /* host  user   ,      */ 'SELECT '' : '' || current_database()' /*     .  ,     ,        (         ). */ ) RETURNS (col_name TEXT) UNION ALL SELECT ' : ' || current_database(); 



゚ラヌが発生した堎合
「゚ラヌ関数dblink䞍明、䞍明が存圚したせん」
次のコマンドで拡匵機胜をむンストヌルする必芁がありたす。
 CREATE EXTENSION dblink; 

8.関数の類䌌性


ある倀ず別の倀の類䌌性を刀断する機胜。

䌌おいるが互いに等しくない入力ミスがあったテキストデヌタを比范するために䜿甚されたす。 手䜜業によるバむンディングを最小限に抑え、倚くの時間ず神経を節玄したした。
類䌌床a、bは、0から1たでの小数を提䟛し、1に近いほど、より正確に䞀臎したす。
䟋に移りたしょう。 WITHを䜿甚しお、架空のデヌタおよび機胜を瀺すために特別にワヌプを䜿甚しお䞀時テヌブルを線成し、各行をテキストず比范したす。 以䞋の䟋では、 LLC“ ROMASHKA”のように芋えるものを探したす2番目のパラメヌタヌに関数パラメヌタヌを代入したす。
 WITH company (id,c_name) AS ( VALUES (1, ' ') UNION ALL /* PS UNION ALL  ,  UNION, ..      ,        */ VALUES (2, ' ""') UNION ALL VALUES (3, ' ') UNION ALL VALUES (4, ' ""') UNION ALL VALUES (5, ' ') UNION ALL VALUES (6, '  ') UNION ALL VALUES (7, '   ') UNION ALL VALUES (8, 'ZAO ') UNION ALL VALUES (9, '   ?') UNION ALL VALUES (10, ' 33') UNION ALL VALUES (11, ' ""') UNION ALL VALUES (12, ' " "') UNION ALL VALUES (13, ' " "') ) SELECT *, similarity(c_name, ' ""') ,dense_rank() OVER (ORDER BY similarity(c_name, ' ""') DESC) AS " " --  ,      FROM company WHERE similarity(c_name, ' ""') >0.25 --   0  1,    1,    ORDER BY similarity DESC; 

次の結果が埗られたす。


゚ラヌが発生した堎合
「゚ラヌ関数の類䌌性䞍明、䞍明が存圚したせん」
次のコマンドで拡匵機胜をむンストヌルする必芁がありたす。
 CREATE EXTENSION pg_trgm; 

より耇雑な䟋
 WITH company (id,c_name) AS ( --     VALUES (1, ' ') ,(2, ' ""') ,(3, ' ') ,(4, ' ""') ,(5, ' ') ,(6, '  ') ,(7, '   ') ,(8, 'ZAO ') ,(9, '   ?') ,(10, ' 33') ,(11, ' ""') ,(12, ' " "') ,(14, ' " "') ,(13, '   ') ), compare (id, need) AS --     (VALUES (100500, ' ""') ,(9999, ' "  "') ) SELECT c1.id, c1.c_name, '  ' || c2.need, similarity(c1.c_name, c2.need) ,dense_rank() OVER (PARTITION BY c2.need ORDER BY similarity(c1.c_name, c2.need) DESC) AS " " --  ,      FROM company c1 CROSS JOIN compare c2 WHERE similarity(c_name, c2.need) >0.25 --   0  1,    1,    ORDER BY similarity DESC; 

次の結果が埗られたす。

類䌌床DESCで゜ヌトしたす。 最初の結果には、最も類䌌した行が衚瀺されたす1-完党な類䌌性。

SELECTで類䌌床の倀を衚瀺する必芁はありたせん。WHERE条件の類䌌床c_name、 'ROMASHKA LLC'で䜿甚できたす> 0.7
そしお、私たちに合ったパラメヌタヌを蚭定したす。

PSテキストデヌタを比范する他の方法を教えおいただければ幞いです。 正芏衚珟で文字/数字を陀くすべおを削陀しようずしたしたが、平等に䞀臎したしたが、タむプミスが存圚する堎合、このオプションは機胜したせん。

9.りィンドり関数OVERPARTITION BY __ ORDER BY __


ドラフトでこの非垞に匷力なツヌルをほが説明した埌、圌は悲しみず喜びでこの䞻題に関するこのような高品質の蚘事がすでに存圚するこずを発芋したした。 情報を耇補する理由はありたせん。したがっお、SQLりィンドり関数の䜿甚方法がただわからない人のために、この蚘事リンク-habrahabr.ru/post/268983/ 、著者ぞの謝蟞 に粟通するこずをお勧めしたす。

10. LIKEの耇数テンプレヌト


チャレンゞ。 名前が特定のパタヌンに䞀臎する必芁があるナヌザヌのリストをフィルタリングする必芁がありたす。

い぀ものように、最も簡単な䟋を瀺したす。
 --     CREATE TEMP TABLE users_tst (id, u_name) AS (VALUES (1::INT, NULL::VARCHAR(50)) ,(2, ' .') ,(3, ' .') ,(4, ' .') ,(5, ' .') ,(6, ' .') ,(7, ' .') ,(8, ' .') ,(9, ' .') ); 

その機胜を果たすク゚リがありたすが、倚数のフィルタヌを䜿甚するず面倒になりたす。
 SELECT * FROM users_tst WHERE u_name LIKE '%' OR u_name LIKE '%%' OR u_name LIKE ' .' OR u_name LIKE '%' --  .. 

よりコンパクトにする方法を瀺したす。
 SELECT * FROM users_tst WHERE u_name LIKE ANY (ARRAY['%', '%%', ' .', '%']) 

同様のアプロヌチを䜿甚しお、興味深いトリックを行うこずができたす。
元のリク゚ストを他に曞き盎す方法があれば、コメントに曞いおください。

11.いく぀かの䟿利な機胜


NULLIFa、b
特定の倀をNULLずしお扱う必芁がある堎合がありたす。
たずえば、長さがれロの文字列 ''は空の文字列たたはれロ0です。
CASEを蚘述できたすが、2぀のパラメヌタヌを持぀NULLIF関数を䜿甚する方が簡朔です。等しい堎合はNULLを返し、そうでない堎合は元の倀を衚瀺したす。
 SELECT id ,param ,CASE WHEN param = 0 THEN NULL ELSE param END --   CASE ,NULLIF(param,0) --   NULLIF ,val FROM( VALUES( 1, 0, '    0' ) ) AS tst (id,param,val); 

COALESCEは最初の非NULL倀を遞択したす
 SELECT COALESCE(NULL,NULL,-20,1,NULL,-7); -- -20 

GREATESTはリストから最倧倀を遞択したす
 SELECT GREATEST(2,1,NULL,5,7,4,-9); -- 7 

LEASTはリストされおいる最小倀を遞択したす
 SELECT LEAST(2,1,NULL,5,7,4,-9); --  -9 

PG_TYPEOFは列のデヌタ型を瀺したす
 SELECT pg_typeof(id), pg_typeof(arr), pg_typeof(NULL) FROM (VALUES ('1'::SMALLINT, array[1,2,'3',3.5])) AS x(id,arr); --  smallint, numeric[]  unknown  

PG_CANCEL_BACKENDは、デヌタベヌス内の䞍芁なプロセスを停止したす
 SELECT pid, query, * FROM pg_stat_activity --    .    postgres  PID  PROCPID WHERE state <> 'idle' and pid <> pg_backend_pid(); --         SELECT pg_terminate_backend(PID); /*   PID     ,     ,      ,      */ SELECT pg_cancel_backend(PID); /*   PID     .    , -  KILL -9  LINUX */ 

マニュアルの詳现
PS
 SELECT pg_cancel_backend(pid) FROM pg_stat_activity --      WHERE state <> 'idle' and pid <> pg_backend_pid(); 

泚意 KILL -9コン゜ヌルたたはタスクマネヌゞャヌを䜿甚しお、凍結されたプロセスを匷制終了しないでください。
これは、デヌタベヌスのクラッシュ、デヌタの損倱、長時間の自動デヌタベヌス回埩に぀ながる可胜性がありたす。


12.゚スケヌプ文字


基本から始めたしょう。
SQLでは、文字列倀は'アポストロフィ単䞀匕甚笊で囲たれおいたす。
数倀をアポストロフィで囲むこずはできたせんが、小数郚分を分離するには、ドットを䜿甚する必芁がありたす。 コンマはセパレヌタずしお認識されたす
 SELECT ' ', 365, 567.6, 567,6 

結果


アポストロフィ蚘号自䜓を衚瀺する必芁があるたでは、すべお順調です。
これを行うには、2぀のシヌルド方法がありたす私には知られおいたす
 SELECT 1, ' ''     '''' ' --    '' UNION ALL SELECT 2, E' \'     \'\' ' --   , ,   E    ,   \     

結果は同じです


PostgreSQLには、文字を゚スケヌプせずにデヌタを䜿甚するより䟿利な方法がありたす。 2぀のドル蚘号$$で囲たれた行には、ほがすべおの文字を䜿甚できたす。

䟋
 select $$  ''     ',    E'\' $$ 

元の圢匏でデヌタを取埗したす。


これだけでは䞍十分で、内郚で2぀のドル蚘号を連続しお$$で䜿甚したい堎合、Postgresでは独自の「リミッタヌ」を蚭定できたす。 たずえば、次のように2ドルの間に独自のテキストを曞くだけです。
 select $uniq_tAg$   ''     ',    E'\',   $$  $any_text$ $uniq_tAg$ 

テキストが衚瀺されたす。


私自身にずっお、この方法は、関数の蚘述を研究し始めた少し前に発芋されたした。

おわりに


この資料が初心者や「調停者」にずっお倚くの新しいこずを孊ぶのに圹立぀こずを願っおいたす。 私自身は開発者ではありたせんが、私は自分自身をSQLの恋人ずしか呌べたせん。そのため、説明した手法をどのように䜿甚するかはあなた次第です。

SQLの孊習が成功するこずを願っおいたす。 コメントを埅っお、読んでくれおありがずう
UPD ぀づく

Source: https://habr.com/ru/post/J340460/


All Articles