まれなSQL

入門



テクノロジー、プログラミング言語、標準に頻繁に出くわすと、それらの機能の特定の状況、それらが使用される境界が形成されます。 知識の強化された視野を広げる例が明らかになるまで、これは長い間続くことができます。 今日は、そのような例についてお話しし、SQL言語でそれらを実証したいと思います。 この記事では、興味深い珍しいデザイン、忘れられた表現、奇妙なトリックがあなたを待っています。 興味のある方、猫へようこそ。



ニュアンス



この記事は誰のためによく聞かれますか? しかし、私に信じてください。答えを出すのは必ずしも簡単なことではありません。一方で、何かに驚きにくい忍者開発者と、若いパダワンがいます。 しかし、私が確実に言えることの1つは、SQLに興味のある読者のためです。SQLには、小さくても非常に興味深い詳細で豊富な画像を補完することができます。 この記事には、最大1、2行のSQLクエリのキロメートルページはなく、私の意見ではまれです。 しかし、私は完全に率直になりたいので、もしあなたがsqlからあなたであるなら、この記事は退屈に見えるでしょう。 この記事のすべての例は、1番目と4番目を除き、SQL-92標準に起因しています。



データ



私たちの生活を簡素化するために、特定の瞬間をテストする簡単なデータプレートを投げました。簡潔にするために、それらの実験結果を示します。 PostgreSqlですべてのリクエストをチェックします。
スクリプトとデータ表
CREATE TABLE goods( id bigint NOT NULL, name character varying(127) NOT NULL, description character varying(255) NOT NULL, price numeric(16,2) NOT NULL, articul character varying(20) NOT NULL, act_time timestamp NOT NULL, availability boolean NOT NULL, CONSTRAINT pk_goods PRIMARY KEY (id)); INSERT INTO goods (id, name, description, price, articul, act_time, availability) VALUES (1, '', '', 100.00, 'TR-75', {ts '2017-01-01 01:01:01.01'}, TRUE); INSERT INTO goods (id, name, description, price, articul, act_time, availability) VALUES (2, '', '', 200.00, 'PR-75', {ts '2017-01-02 02:02:02.02'}, TRUE); INSERT INTO goods (id, name, description, price, articul, act_time, availability) VALUES (3, '', '', 300.00, 'ZR-75', {ts '2017-01-03 03:03:03.03'}, TRUE); INSERT INTO goods (id, name, description, price, articul, act_time, availability) VALUES (4, '', '', 400.00, 'AR-75', {ts '2017-01-04 04:04:04.04'}, FALSE); INSERT INTO goods (id, name, description, price, articul, act_time, availability) VALUES (5, '', '', 500.00, 'BR-75', {ts '2017-01-05 05:05:05.05'}, FALSE);
      
      





id お名前 説明 価格 アーティクル act_time 利用可能
1 スリッパ 柔らかい 100.00 TR-75 2017-01-01 01:01:01.01 本当
2 200.00 PR-75 2017-01-02 02:02:02.02 本当
3 毛布 ダウン 300.00 ZR-75 2017-01-03 03:03:03.03 本当
4 枕カバー 灰色 400.00 AR-75 2017-01-04 04:04:04.04
5 シート シルク 500.00 BR-75 2017-01-05 05:05:05.05




お問い合わせ



1.二重引用符



そして、私が最初に持っていることは簡単な質問です。 二重引用符を使用したSQLクエリの例を挙げていただけますか? はい、シングルではなく、ダブルですか?

二重引用符の例
 SELECT name " " FROM goods
      
      



製品名
スリッパ
毛布
枕カバー
シート


これを初めて見たとき、私はとても驚きました。 二重引用符を単一引用符に変更しようとすると、結果は完全に異なります!

一重引用符の例
 SELECT name ' ' FROM goods WHERE id = 1
      
      





お名前
これはデータです




これは実際の開発にはあまり有用な例ではないように思えるかもしれません。 これは私にはそうではありません。 今では、すべてのsql-stubで積極的に使用しています。 一番下の行は、半年後に40列のsqlクエリに戻ったときに簡単です。名前がどのように名前を救うかについてです。 SQL-92については言及していませんが、最新版では二重引用符について言及しています。



2.擬似テーブル。 SQL-92



用語の観点からは少し不正確ですが、本質は単純です-テーブルはFROMセクションのサブクエリの結果です。 この記事でおそらく最も有名な事実。

擬似テーブル
 SELECT mock.nickname "", (CASE WHEN mock.huff THEN '' ELSE '' END) "?" FROM (SELECT name AS nickname, availability AS huff FROM goods) mock
      
      



ニックネーム 気分を害した?
スリッパ はい
はい
毛布 はい
枕カバー いや
シート いや
この例では、モックは擬似テーブル(仮想テーブルとも呼ばれます)です。 当然、それらは本当の意味を誤解することを意図していません。 この例。



3.データブロックのコンストラクター。 SQL-92



良い翻訳や解釈が見つからなかったからこそ、それは怖いように聞こえます。 そしていつものように、例を使って説明する方が簡単です:
データブロックコンストラクターの例
 SELECT name " ", price "" FROM (VALUES ('', 100.00), ('', 200.00)) AS goods(name, price)
      
      



製品名 価格
スリッパ 100.00
200.00
FROMセクションはVALUESキーワードを使用し、その後に行ごとに括弧で囲まれたデータが続きます。 一番下の行は、テーブルからデータを選択するのではなく、その場で作成し、テーブルを「呼び出し」、列に名前を付けてから、自由裁量で使用することです。 このことは、いくつかのテーブル(ローカルデータベース)にデータがない場合にさまざまなsqlクエリケースをテストするときに非常に有用であることがわかりました。また、テーブルの接続性と制限のために、挿入の書き込みが面倒です。



4.時刻、日付、および日時



おそらく、誰もが問い合わせに遭遇し、時間、日付、または日時を示す必要がありました。 多くのDBMSは、これらの型を操作するために、それぞれリテラルt、d、およびtsをサポートしています。 ただし、例を使用して説明する方が簡単です。
リテラルtsの例
 SELECT name " ", act_time " " FROM goods WHERE act_time = {ts '2017-01-01 01:01:01.01'}
      
      



製品名 正確な時間
スリッパ 2017-01-01 01:01:01.01
リテラルdおよびtについては、すべてが類似しています。

読者に誤解を招く恐れがあることをおizeびしますが、段落4で述べられていることはすべてSQL言語には適用されませんが、JDBCでのクエリの前処理の可能性について言及しています。



5.拒否。 SQL-92



私たちは皆NOT演算子について知っていますが、述語グループと単一の列の両方に適用できることを忘れがちです:

否定の例
 SELECT id, name, availability FROM goods WHERE NOT availability --   SELECT id, name FROM goods WHERE NOT (id = 1 OR id = 2 OR id = 3)
      
      



id お名前 利用可能
4 枕カバー
5 シート




6.データブロックの比較。 SQL-92



もう一度、私は用語をおforびします。 これは私のお気に入りの例の1つです。
データブロックの比較の例
 SELECT * FROM goods WHERE (name, price, availability) = ('', 400.00, FALSE) --    SELECT * FROM goods WHERE name = '' AND price = 400.00 AND availability = FALSE
      
      



id お名前 説明 価格 アーティクル act_time 利用可能
4 枕カバー 灰色 400.00 AR-75 2017-01-04 04:04:04.04
例からわかるように、データブロックの比較は、 ビット単位のvalue_1 _block_1 = value_1 _block_2、value_2 _block_1 = value_2_ _block_2、value_3 _block_1 = value_3_block_2を比較することに似ています。



7. ANY、SOME、またはALL修飾子を持つ比較演算子。 SQL-92



ここで説明が必要です。 しかし、いつものように、最初の例
ALLとの比較例
 SELECT id, name FROM goods WHERE id > ALL (SELECT id FROM goods WHERE availability)
      
      



id お名前
4 枕カバー
5 シート
この場合、 ALLとはどういう意味ですか? また、識別子(この場合は4と5)が選択条件を満たす行のみが、サブクエリで見つかった値(1、2、3)よりも大きいことを意味します。 4は1より大きく2未満で3未満です。 ALLANYに置き換えるとどうなりますか?

ANYとの比較例
 SELECT id, name FROM goods WHERE id > ANY (SELECT id FROM goods WHERE availability)
      
      



id お名前
2
3 毛布
4 枕カバー
5 シート
この場合、 ANYとはどういう意味ですか? また、識別子(この例では2、3、4、5)が選択条件を満たす行のみが、サブクエリで見つかった値の少なくとも1つ (1、2、3)よりも大きいことを意味します。 私自身は、 ALLANDに関連付け、 ANYORに関連付けました。 いくつかの類似物があります。



8.問い合わせ/問い合わせ中の作業のオペレーター。 SQL-92



UNIONまたはUNION ALL演算子を使用して、2つのクエリを互いに結合できることはよく知られています。 これはよく使用されます。 しかし、さらに2つのEXCEPTおよびINTERSECTステートメントがあります。

例以外
 SELECT * FROM goods EXCEPT (SELECT * FROM goods WHERE availability)
      
      



id お名前 説明 価格 アーティクル act_time act_time
4 枕カバー 灰色 400.00 AR-75 2017-01-04 04:04:04.04
5 シート シルク 500.00 BR-75 2017-01-05 05:05:05.05
実際には、2番目のセットのデータは最初の値のセットから除外されます。

INTERSECTの例
 SELECT * FROM goods WHERE id > 2 INTERSECT (SELECT * FROM goods WHERE availability)
      
      



id お名前 説明 価格 アーティクル act_time act_time
3 毛布 ダウン 300.00 ZR-75 2017-01-03 03:03:03.03 本当
実際、最初の値のセットと2番目のセットは交差しています。

それだけです、ご清聴ありがとうございました。



ソース



SQL-92、SQL-99、およびSQL-2003のBNF文法

SQLチュートリアル



編集者



N1。 建設的な批判に対するstreetflushに感謝します。 言語の標準とそうでないものについての情報を含む記事を入力しました。

N2。 ポイント4は修正され、ts / d / tはSQL言語の一部ではないという説明があります。 ご注意ありがとうございます。



All Articles