2017-10-16 1 views
0

Windows 용 sqlite3 버전 3.20.1을 실행하는 sqlite3에 매우 이상한 문제가 있습니다.SQLite 강제로 정렬 선택

두 테이블의 동일한 SELECT 쿼리가 다른 결과를 생성합니다. 그러나 열 데이터 유형 및 데이터는 둘 다 동일합니다. 다음은 CREATE 및 INSERT 문입니다.

CREATE TABLE key(key INTEGER UNIQUE NOT NULL); 
CREATE TABLE map(key INTEGER UNIQUE NOT NULL, char TEXT); 

WITH RECURSIVE cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt LIMIT 9999) INSERT INTO key(key) SELECT x FROM cnt WHERE x >=1000 ORDER BY random(); 
WITH RECURSIVE cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt LIMIT 9999) INSERT INTO map(key) SELECT x FROM cnt WHERE x >=1000 ORDER BY random(); 

이렇게하면 1000에서 9999 사이의 번호를 무작위로 두 열에 모두 삽입해야합니다. 그러나 두 번째 테이블의 SELECT 문은 항상 정렬됩니다. 결과는 다음과 같습니다

sqlite> SELECT key FROM map LIMIT 10; 
1000 
1001 
1002 
1003 
1004 
1005 
1006 
1007 
1008 
1009 
sqlite> SELECT key FROM key LIMIT 10; 
6165 
1856 
2457 
2343 
9095 
8005 
4958 
4781 
8334 
1863 

나는 다음을 시도해 보았습니다.

sqlite> DELETE FROM map; 
sqlite> INSERT INTO map(key) SELECT key FROM key; 
sqlite> 
sqlite> SELECT key FROM map LIMIT 10; 
1000 
1001 
1002 
1003 
1004 
1005 
1006 
1007 
1008 
1009 

여전히 분류되어 있습니다. REPLACE를 사용하는 것도 도움이되지 못했습니다. id 열을 먼저 추가하여 테이블 스키마를 약간 변경하려고 시도했지만 성공하지 못했습니다.

일부 실험을 마친 후 SELECT *은 올바른 순서로 표시되지만 SELECT key은 정렬 된 결과를 제공함을 발견했습니다.

sqlite> SELECT * FROM map LIMIT 10; 
8418| 
5869| 
9753| 
2886| 
8354| 
8244| 
4063| 
6692| 
5440| 
3508| 

설명 할 수 있습니까? 버그 또는 기능입니까? 예상 출력을 얻으려면 어떻게해야합니까?

답변

0

documentation는 말한다 :

둘 이상의 행을 반환하는 SELECT 문은 ORDER BY 절이없는 경우 , 행이 리턴되는 순서는 정의되지 않습니다.

쿼리가 임의의 순서로 행을 반환하도록하려면 쿼리 자체에 ORDER BY random()을 사용해야합니다.

(내부 순서로 행을 반환 ORDER BY rowid를 사용하지만,이 WITHOUT ROWID tables 작동하지 않습니다합니다.)에 UNIQUE 제약 조건에 대한 인덱스는 다음 테이블은 하나 개의 열을 포함하고 있기 때문에 적은 저장소를 사용


.디스크에서 적은 데이터를 읽는 것은 쿼리를 빠르게 만들기 때문에 당신은이 칼럼을 읽을 수 그래서 한 , 질의 최적화 (A covering index 등) 인덱스에서 직접 값을 읽을 것을 선호 :

sqlite> EXPLAIN QUERY PLAN SELECT key FROM map; 
0|0|0|SCAN TABLE map USING COVERING INDEX sqlite_autoindex_map_1 

을 그 돌려 주어지는 행은, 단지 부작용뿐입니다.

+0

고마워요. 매우 도움이된다! – Dawood

+0

'ORDER BY ROWID'를 추가하면 예상 한 결과를 얻을 수 있습니다. – Dawood

0

이렇게하면 1000에서 9999 사이의 숫자를 임의로 정렬하여 두 열에 모두 삽입해야합니다. 그러나 두 번째 테이블의 SELECT 문은 항상 정렬됩니다.

당신은 SQL을 이해하지 못합니다. SQL 테이블은 을 나타내며 집합 번호는입니다. 즉, SQL 엔진이 원하는 데이터를 저장하는 방법을 결정할 수 있습니다.

SQL 쿼리는 집합을 반환합니다. 즉, 주문을 지정하지 않으면 SQL 엔진이 결과 집합의 순서를 결정할 수 있습니다.

이 경우 SQLite는 테이블의 고유 키를 기반으로 결과 집합을 반환합니다. 쿼리의 인덱스를 사용하고 있습니다. (. SQLite는 실제로 고유 키가 테이블의 기본 키는 것을 결정 할 수있다)

+0

감사합니다. 하지만 'select *'결과가 같은 "기본 키"에 의해 정렬되어야하는 경우'select column'과 다른 이유는 무엇입니까? 이러한 동작에 대한 참조를 추가 할 수 있습니까? – Dawood

+0

@Dawood. . . 한 경우에는 고유 색인을 사용하고 다른 경우에는 고유 색인을 사용합니다. 특정 순서로 데이터를 원한다면 'order by'를 사용하십시오. –