2012-10-13 23 views
2

我已經寫了像SQL查詢:如何克服的IN原因的限制,在SQL查詢

select field1, field2 from table_name; 

問題是這樣的查詢將返回1萬條記錄/或超過10萬分的記錄。 我有一個目錄,其中包含field1的輸入文件(大約20,000到50,000條記錄)。這是我關心的主要數據。 使用perl腳本,我從目錄中提取。 但是,如果我寫這樣的查詢:

select field1 , field2 from table_name 
where field1 in (need to write a query to take field1 from directory); 

如果我用事業那麼它處理1000個條目的限制,那我應該怎麼克服的IN原因的限制?

+0

什麼數據庫系統對'in'有1K限制? –

+1

@eakron:Oracle在IN子句中限制爲1000個字符(即常量)。其他DBMS也有類似的限制。 –

回答

4

在任何DBMS中,我會將它們插入臨時表並執行JOIN以解決IN子句對列表大小的限制。

E.g.

CREATE TABLE #idList 
(
    ID INT 
) 
INSERT INTO #idList VALUES(1) 
INSERT INTO #idList VALUES(2) 
INSERT INTO #idList VALUES(3) 

SELECT * 
FROM 
    MyTable m 
    JOIN #idList AS t 
    ON m.id = t.id 

在SQL Server 2005中,我們在以前的項目之一,我們使用轉換是查詢另一個數據存儲(Lucene索引)轉換成XML的結果值列表,並把它作爲在XML變量SQL查詢並使用XML數據類型的nodes()函數將其轉換爲表格,並使用該函數執行JOIN

DECLARE @IdList XML 
SELECT @idList = ' 
<Requests> 
    <Request id="1" /> 
    <Request id="2" /> 
    <Request id="3" /> 
</Requests>' 

SELECT * 
FROM 
    MyTable m 
    JOIN (
      SELECT id.value('(@id)[1]', 'INT') as 'id' 
      FROM @idList.nodes('/Requests/Request') as T(id) 
     ) AS t 
    ON m.id = t.id 
+0

我有oracle和sql作爲數據庫。而且,我沒有得到你的XML點。請你能詳細說明一個例子嗎?如果你這樣做會很好。 –

+0

請參閱有關如何在SQL Server 2005或更高版本中支持臨時表(Oracle支持)和XML表選項的任何數據庫中使用臨時表選項的更新。 – Vikdor

+0

@Vikdor我不喜歡每次查詢運行時重新創建整個表的方法。 Imho,最好做一次,然後在必要時更新。 – aefxx

0

你可以在1000個IDS 50名名單分割你的IDS 50'000,做每一個這樣的名單查詢,並收集結果集在Perl。

+0

嗨@meriton,我應該如何處理你的答案。如何重新查詢50個列表?請給我提供例子。我是否應該加入50個列表的結果? –

1

Vikdor是對的,你不應該用IN()子句來查詢它,它使用JOIN表的速度更快,內存效率更高。

擴大他的答案,我會推薦以下方法:

  1. 通過Perl中獲取所有輸入文件列表的一些巧妙的方法來計算你的列表中的散列值,是獨特
  2. 思考和基於所有輸入文件(我建議使用文件名或類似文件)
  3. 該散列將用作存儲輸入文件名的表的名稱(將其視爲一個準臨時表,一旦散列發生變化就會被丟棄)
  4. JOIN該表返回正確的記錄

對於第2步,您可以使用cronjob或計算每當實際需要查詢(雖然會延遲響應)。爲了得到這個權利,你需要考慮文件被添加/刪除的可能性。

對於第3步,您需要一些邏輯,在當前散列值與上次執行不同時刪除先前生成的表,然後重新創建以當前散列值命名的表。

對於準臨時表的名字,我會建議沿着

input_files_XXX (.i.e. prefix_<hashvalue>) 

這使得它更容易知道什麼陳舊的桌子砸線的東西。

0

Oracle明智地說,使用臨時表的最佳解決方案 - 沒有索引的情況下不會給你太多的性能是使用嵌套的表格類型。

CREATE TYPE my_ntt是directory_rec的表;

然後創建一個函數f1,它返回一個my_ntt類型的變量並在查詢中使用。

從table_name中選擇field1,field2 where table1中的field1(cast(f1 as my_ntt));

+0

您能否發表一個例子? –