22

テーブルを含む SQLite データベースがあるとします。

sqlite> create table person (id integer, firstname varchar, lastname varchar);

ここで、テーブルにあるすべてのエントリを取得したいと考えています。

sqlite> select t0.id, t0.firstname, t0.lastname from person t0;

これはうまく機能し、これは私が使用するものです。ただし、SQL を生成する Apple のフレームワーク (Core Data) を使用しました。このフレームワークは、わずかに異なる SQL クエリを生成します。

sqlite> select 0, t0.id, t0.firstname, t0.lastname from person t0;

このフレームワークによって生成されるすべての SQL クエリは、"select 0," で始まります。何故ですか?

説明コマンドを使用して何が起こっているのかを確認しようとしましたが、これは決定的ではありませんでした-少なくとも私にとっては。

sqlite> explain select t0.id, t0.firstname, t0.lastname from person t0;
addr        opcode      p1          p2          p3          p4          p5          comment   
----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------
0           Trace       0           0           0                       00          NULL      
1           Goto        0           11          0                       00          NULL      
2           OpenRead    0           2           0           3           00          NULL      
3           Rewind      0           9           0                       00          NULL      
4           Column      0           0           1                       00          NULL      
5           Column      0           1           2                       00          NULL      
6           Column      0           2           3                       00          NULL      
7           ResultRow   1           3           0                       00          NULL      
8           Next        0           4           0                       01          NULL      
9           Close       0           0           0                       00          NULL      
10          Halt        0           0           0                       00          NULL      
11          Transactio  0           0           0                       00          NULL      
12          VerifyCook  0           1           0                       00          NULL      
13          TableLock   0           2           0           person      00          NULL      
14          Goto        0           2           0                       00          NULL 

2 番目のクエリのテーブルは次のようになります。

sqlite> explain select 0, t0.id, t0.firstname, t0.lastname from person t0;
addr        opcode      p1          p2          p3          p4          p5          comment   
----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------
0           Trace       0           0           0                       00          NULL      
1           Goto        0           12          0                       00          NULL      
2           OpenRead    0           2           0           3           00          NULL      
3           Rewind      0           10          0                       00          NULL      
4           Integer     0           1           0                       00          NULL      
5           Column      0           0           2                       00          NULL      
6           Column      0           1           3                       00          NULL      
7           Column      0           2           4                       00          NULL      
8           ResultRow   1           4           0                       00          NULL      
9           Next        0           4           0                       01          NULL      
10          Close       0           0           0                       00          NULL      
11          Halt        0           0           0                       00          NULL      
12          Transactio  0           0           0                       00          NULL      
13          VerifyCook  0           1           0                       00          NULL      
14          TableLock   0           2           0           person      00          NULL      
15          Goto        0           2           0                       00          NULL     
4

3 に答える 3

17

一部のフレームワークは、そのテーブルの行が返されたかどうかを疑いなく伝えるためにこれを行います。

検討

  A      B
+---+  +---+------+
| a |  | a | b    |
+---+  +---+------+
| 0 |  | 0 |    1 |
+---+  +---+------+
| 1 |  | 1 | NULL |
+---+  +---+------+
| 2 |
+---+

SELECT A.a, B.b
FROM A
LEFT JOIN B
ON B.a = A.a

  Results
+---+------+
| a | b    |
+---+------+
| 0 |    1 |
+---+------+
| 1 | NULL |
+---+------+
| 2 | NULL |
+---+------+

この結果セットではa = 1、 がテーブル B に存在することは確認できませんが、存在しa = 2ません。その情報を取得するには、テーブル b から null 非許容式を選択する必要があります。これを行う最も簡単な方法は、単純な定数値を選択することです。

SELECT A.a, B.x, B.b
FROM A
LEFT JOIN (SELECT 0 AS x, B.a, B.b FROM B) AS B
ON B.a = A.a

  Results
+---+------+------+
| a | x    | b    |
+---+------+------+
| 0 |    0 |    1 |
+---+------+------+
| 1 |    0 | NULL |
+---+------+------+
| 2 | NULL | NULL |
+---+------+------+

これらの定数値が厳密に必要とされない状況はたくさんあります。たとえば、結合がない場合や、代わりに b から null 非許容の列を選択できる場合などです。無条件に含まれるだけです。

于 2012-11-04T14:55:55.300 に答える
9

句を動的に生成するコードがあるWHERE場合、通常は句を次のように開始します。

WHERE 1 = 1

次に、追加の条件を追加するループは、常に同じ形式で各条件を追加します。

AND x = y

これが最初の条件であるかどうかを確認する条件付きロジックを配置する必要はありません。「これが最初の条件である場合はWHEREキーワードで開始し、そうでない場合はキーワードを追加しANDます。

したがって、同様の理由でこれを行うフレームワークを想像できます。ステートメントを a で開始すると、SELECT 0後続の列を追加するコードは、条件ステートメントなしでループすることができます。, colx「これが最初の列の場合は、列名の前にコンマを置かないでください。それ以外の場合はそうします」という行に沿って、条件付きチェックなしで毎回追加するだけです。

疑似コードの例:

String query = "SELECT 0";

for (Column col in columnList)
    query += ", col";
于 2012-11-04T16:38:37.193 に答える
0

知っているのは Apple だけですが、私は 2 つの可能性を考えています。

  1. ダミー列を挿入すると、実際の出力列が 0 ではなく 1 から始まるように番号が付けられます。既存のインターフェイスが 1 ベースの番号付けを既に想定している場合、SQL バックエンドでこのようにするのが最も簡単な解決策だったかもしれません。

  2. 複数のサブクエリを使用して複数のオブジェクトのクエリを作成する場合、次のような値を使用して、レコードがどのサブクエリから発生したかを判断できます。

    SELECT 0, t0.firstname, ... FROM PERSON t0 WHERE t0.id = 123
    UNION ALL
    SELECT 1, t0.firstname, ... FROM PERSON t0 WHERE t0.id = 456 
    

    (Core Data が実際にこれを行うかどうかはわかりません。)


出力EXPLAINは、唯一の違いは (アドレス 4 で) 2 番目のプログラムが余分な列をゼロに設定することであるため、パフォーマンスの違いは最小限であることを示しています。

于 2012-11-04T15:38:45.017 に答える