我想根据某些条件阅读EmpID
表中的EMP
。对于每个EmpID
,我需要在另一个表中执行一些操作。如何一次读取EmpID
的单个值。
提前致谢
答案 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