2012-11-04 14 views
20

、私はテーブルが含まれているSQLiteのデータベースを持っているとしましょう。なぜSELECT 0、...の代わりに、SELECT

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クエリは「0を選択」で始まります。何故ですか?

私はexplainコマンドを使って何が起こっているのかを調べようとしましたが、これは決して決してわかりませんでした。

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  

答えて

15

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

この結果セット内

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からnullableでない式を選択する必要があります。最も単純な方法は、単純な定数値を選択することです。

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可能列を選択することができるとき、彼らは起こさない何を持っていないときに、これらの定数の値は厳密例えば、必要とされていない状況がたくさんありますどんな害もありますので、無条件に含めることができます。

+0

しかし、テーブルBから一定の '0'は、*ではありません。すべての結果レコードに無条件に戻されます。 –

+0

@ CL。私が意味することをより明確にするために編集されました。 – hvd

+0

しかし、Core Dataは最も外側のクエリに '0'を置きます。 –

0

のみAppleは知っている...しかし、私は二つの可能性を参照してください。

  1. はダミー列を挿入すると、いくつかの既存のインタフェースを既にワン仮定した場合は1、いない0から始まる実際出力列が番号が付けられていることを保証します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 
    

    コアデータならば(私は実際に知りませんこれはない。)


あなたEXPLAIN出力は、唯一の違いは、第2のプログラムがゼロに余分な列を設定すること)は、アドレス4に(sであることを示していますoパフォーマンスの差はごくわずかです。

8

私は動的にWHERE句を生成するためのコードを持っているとき、私は通常で句を開始します。

WHERE 1 = 1 

その後、追加条件を追加するためのループが常に同じ形式で各条件を追加します。

AND x = y 

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

同様の理由でこれを行うフレームワークを想像することができます。 SELECT 0を使用してステートメントを開始すると、後続の列を追加するコードは、条件ステートメントなしのループになる可能性があります。 , colxを追加するには、「これが最初の列の場合は列名の前にコンマを入れないでください。

例擬似コード:

String query = "SELECT 0"; 

for (Column col in columnList) 
    query += ", col"; 
+0

私はあなたの意見を見ますObjective-Cでは、次のように列名を単純に結合することができます。 [@ [@ "firstName"、@ "lastName"] componentsJoinedByString:@ "、"]]; ここで必要な場合は不要です。 –

+0

これは厳密に私が避けるべきコードの種類でしょう:) – Glenn

+0

forループの代わりにcomponentsJoinedByStringを使用します。たぶんその味の問題... :) –

関連する問題