SQL Server 2008中的数组类似功能

时间:2010-10-01 10:53:57

标签: sql-server sql-server-2008

我想根据某些条件阅读EmpID表中的EMP。对于每个EmpID,我需要在另一个表中执行一些操作。如何一次读取EmpID的单个值。

提前致谢

5 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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

答案 2 :(得分:0)

使用基于集合的SQL逻辑方法始终是首选方法。从这个意义上讲,DanDan是一个可以接受的回应。 或者,您可以使用SQL游标。虽然资源很重,但它们允许您遍历集合并在每一行上应用一些逻辑。

DECLARE @EMPID char(11)

DECLARE c1 CURSOR READ_ONLY
FOR
SELECT EmpID
FROM EMP

WHERE * 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

答案 3 :(得分:0)

DanDan's Answer开始,T-SQL允许你加入FROM语句的UPDATE子句(我不记得这是否是ANSI)。 EG

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

答案 4 :(得分: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命令。

我已经接受了循环并用基于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

如果你有一套合理的项目(不是100,000)来循环,你可以这样做:

--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,@To=@@ROWCOUNT

WHILE @From<@To
BEGIN
    SET @From=@From+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 RowID=@From
    print @msg
    --EXEC (@msg) --<<will not actually send the messages
END