2010-10-01 100 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