2010-10-01 98 views
1

我想根據某些條件在EMP表中讀取EmpID。對於每個EmpID我需要在另一個表中執行一些操作。我怎樣才能一次讀取EmpID的單個值。數組像SQL Server 2008中的功能

在此先感謝

+2

你能解釋「一些操作」? – Andomar 2010-10-01 11:18:29

+0

每個答案旁邊有2個箭頭。如果你喜歡答案,如果它有點幫助,點擊向上按鈕(upvote)是一個很好的習慣,如果答案是完全錯誤的,你可以倒下,儘管人們不喜歡它,而且你也失去了聲望點。如果您的問題收到的答案是正確的,則必須將其標記爲(答案旁邊箭頭下方的綠色檢查標記)。這是一個有責任提問的權利。如果你不這樣做,人們在未來不會急於幫助你。 – AlexanderMP 2010-10-04 07:37:57

回答

0

嘗試從不循環,處理數據集。

您可以一次插入,更新,刪除多行。在這裏一個例子插入多行:

INSERT INTO YourTable 
     (col1, col2, col3, col4) 
    SELECT 
     cola, colb+Colz, colc, @X 
     FROM .... 
      LEFT OUTER JOIN ... 
     WHERE... 

你甚至可以插入在單個語句中多個表:

INSERT INTO YourTable 
     (col1, col2, col3, col4) 
     OUTPUT INSERTED.PK, Inserted.Col2 
      INTO OtherTable (ColA, ColB) 
    SELECT 
     cola, colb+Colz, colc, @X 
     FROM .... 
      LEFT OUTER JOIN ... 
     WHERE... 

當在循環找看看它裏面完成的。如果只是插入/刪除/更新,請重新編寫以使用單個命令。如果有IF,請查看它們是否可以是CASE語句或WHERE條件插入/刪除/更新。如果是這樣,請刪除循環並使用set命令。

我採取了循環,並用基於集合的命令替換它們,並將執行時間從幾分鐘減少到幾秒鐘。我已經採用了許多嵌套循環和過程調用的過程,並保留了循環(不可能只使用插入/刪除/更新),但我刪除了光標,並且看到鎖定/阻塞較少,並且性能大幅提升。這裏有兩個循環的方法是優於光標循環...

,如果你有循環,在一組做這樣的事情:

--this looks up each row for every iteration 
DECLARE @msg VARCHAR(250) 
DECLARE @hostname sysname 

--first select of currsor free loop 
SELECT @hostname= min(RTRIM(hostname)) 
    FROM master.dbo.sysprocesses (NOLOCK) 
    WHERE hostname <> '' 

WHILE @hostname is not null 
BEGIN 
    --just some example of some odd task that requires a loop 
    set @msg='exec master.dbo.xp_cmdshell "net send ' 
     + RTRIM(@hostname) + ' ' 
     + 'testing "' 
    print @msg 
    --EXEC (@msg) --<<will not actually send the messages 

    --next select of cursor free loop 
    SELECT @hostname= min(RTRIM(hostname)) 
     FROM master.dbo.sysprocesses (NOLOCK) 
     WHERE hostname <> '' 
     and hostname > @hostname 
END 

,如果你有一個合理的組項目(不十萬)循環你可以這樣做:

--this will capture each Key to loop over 
DECLARE @msg VARCHAR(250) 
DECLARE @From int 
DECLARE @To  int 
CREATE TABLE #Rows --use a table @variable depending on the number of rows to handle 
(
    RowID  int not null primary key identity(1,1) 
    ,hostname varchar(100) 
) 

INSERT INTO #Rows 
SELECT DISTINCT hostname 
    FROM master.dbo.sysprocesses (NOLOCK) 
    WHERE hostname <> '' 
SELECT @From=0,@[email protected]@ROWCOUNT 

WHILE @From<@To 
BEGIN 
    SET @[email protected]+1 

    --just some example of some odd task that requires a loop 
    SELECT @msg='exec master.dbo.xp_cmdshell "net send ' 
     + RTRIM(hostname) + ' ' 
     + 'testing "' 
     FROM #Rows 
     WHERE [email protected] 
    print @msg 
    --EXEC (@msg) --<<will not actually send the messages 
END 
+0

非常感謝。 – sreekanth 2010-10-04 04:32:46

1
UPDATE otherTable... 
WHERE table2.EmpID IN (SELECT EMP.EmpID FROM EMP WHERE ...) 
+4

如果您發佈的是代碼或XML,**請**在文本編輯器中突出顯示這些行,然後單擊編輯器工具欄上的「代碼」按鈕(101 010)以更好地格式化和語法突出顯示它! – 2010-10-01 11:22:22

+0

非常感謝。 – sreekanth 2010-10-04 04:32:37

0

一般情況下,應避免在SQL程序代碼,但如果你真的需要,使用CURSOR:

DECLARE myCursor CURSOR FAST_FORWARD 
FOR 
    SELECT --your SQL query, a regular SQL query. 
     field1, 
     field2 
    FROM 
     table 

OPEN myCursor; 
FETCH NEXT FROM myCursor 
INTO 
    @var1, --must be pre-declared, of the same types as field1 
    @var2 

WHILE (@@FETCH_STATUS = 0) 
BEGIN 


    --your code use @var1, @var2. Perform queries, do whatever you like. 
    --It will loop through every row fetched by the query in the beginning of the code, and perform this. 


    FETCH NEXT FROM myCursor --do this exactly as before the WHILE loop 
    INTO 
     @var1, 
     @var2 
END 
CLOSE myCursor 
+0

非常感謝您的回覆。其實我正在寫程序,我沒有實現遊標。 – sreekanth 2010-10-01 11:42:02

+0

通過「procedural」我指的是迭代,代碼提供步驟,將任務分解成最小的部分和定義指令序列。與之相反的是聲明性語法,即SQL(還有更多),您可以在其中聲明所需內容,而無需提供有關如何實現它的具體說明。 – AlexanderMP 2010-10-01 11:49:56

+0

非常感謝。 – sreekanth 2010-10-04 04:32:39

0

使用一組爲基礎的方法SQL邏輯始終是首選的方法。從這個意義上講,丹丹的答案是可以接受的。 或者你可以使用SQL遊標。雖然資源很重,但它們將允許您遍歷一組並在每行上應用一些邏輯。

DECLARE @EMPID char(11) 

DECLARE c1 CURSOR READ_ONLY 
FOR 
SELECT EmpID 
FROM EMP 

其中* some_clause *

OPEN c1 

FETCH NEXT FROM c1 
INTO @EMPID 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    PRINT @EMPID 

    FETCH NEXT FROM c1 
    INTO @EMPID 

END 

CLOSE c1 
DEALLOCATE c1 
+0

非常感謝。 – sreekanth 2010-10-04 04:32:44

0

DanDan's Answer繼,T-SQL允許你做一個UPDATE語句的FROM子句中加入(我不記得,如果這是ANSI或不)。 EG

UPDATE 
    OtherTable 
SET 
    Auditing = Employees.EmployeeName 
FROM 
    OtherTable 
    INNER JOIN 
     Employees ON OtherTable.EmpId = Employees.EmpId 
WHERE 
    Employees.DateStarted > '2010-09-01' 
+0

非常感謝。 – sreekanth 2010-10-04 04:32:34