数组像SQL Server 2008中的功能
我想根据某些条件在EMP
表中读取EmpID
。对于每个EmpID
我需要在另一个表中执行一些操作。我怎样才能一次读取EmpID
的单个值。数组像SQL Server 2008中的功能
在此先感谢
尝试从不循环,处理数据集。
您可以一次插入,更新,删除多行。在这里一个例子插入多行:
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
非常感谢。 – sreekanth 2010-10-04 04:32:46
UPDATE otherTable...
WHERE table2.EmpID IN (SELECT EMP.EmpID FROM EMP WHERE ...)
如果您发布的是代码或XML,**请**在文本编辑器中突出显示这些行,然后单击编辑器工具栏上的“代码”按钮(101 010)以更好地格式化和语法突出显示它! – 2010-10-01 11:22:22
非常感谢。 – sreekanth 2010-10-04 04:32:37
一般情况下,应避免在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
非常感谢您的回复。其实我正在写程序,我没有实现游标。 – sreekanth 2010-10-01 11:42:02
通过“procedural”我指的是迭代,代码提供步骤,将任务分解成最小的部分和定义指令序列。与之相反的是声明性语法,即SQL(还有更多),您可以在其中声明所需内容,而无需提供有关如何实现它的具体说明。 – AlexanderMP 2010-10-01 11:49:56
非常感谢。 – sreekanth 2010-10-04 04:32:39
使用一组为基础的方法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
非常感谢。 – sreekanth 2010-10-04 04:32:44
从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'
非常感谢。 – sreekanth 2010-10-04 04:32:34
你能解释“一些操作”? – Andomar 2010-10-01 11:18:29
每个答案旁边有2个箭头。如果你喜欢答案,如果它有点帮助,点击向上按钮(upvote)是一个很好的习惯,如果答案是完全错误的,你可以倒下,尽管人们不喜欢它,而且你也失去了声望点。如果您的问题收到的答案是正确的,则必须将其标记为(答案旁边箭头下方的绿色检查标记)。这是一个有责任提问的权利。如果你不这样做,人们在未来不会急于帮助你。 – AlexanderMP 2010-10-04 07:37:57