T-SQL游标和更新

时间:2010-10-28 19:53:59

标签: sql sql-server tsql sql-server-2008

我使用游标迭代相当大的表。对于每一行,我检查一列中的值是否存在于其他行中。

如果值存在,我想在另一个表中增加value列。 如果没有,我想插入一个值为1的新行。

我通过以下方式检查“if exists”:

IF (SELECT COUNT(*) FROM otherTabe WHERE... > 1)
   BEGIN
      ...
   END
ELSE
   BEGIN
      ...
   END

我不知道如何获取找到的行并更新值。我不想再做一次选择。

我怎样才能有效地做到这一点?

我认为上述检查方法对这种情况并不好。

5 个答案:

答案 0 :(得分:4)

根据数据大小和实际情况,您有两种基本方法:

1)使用MERGE

MERGE TOP (...) INTO table1
USING table2 ON table1.column = table2.column
WHEN MATCHED
 THEN UPDATE SET table1.counter += 1
WHEN NOT MATCHED SOURCE
 THEN INSERT (...) VALUES (...);

需要TOP,因为当你做这样一个巨大的更新时(你提到的表是'大',大是相对的,但是假设真的很大,+ 100MM行)你必须批处理更新,否则你将用一个巨大的交易压倒事务日志。

2)使用光标,正如您尝试的那样。您可以轻松解决原始问题,只需始终更新,然后检查更新的行数:

UPDATE table 
  SET column += 1
WHERE ...;
IF @@ROW_COUNT = 0
BEGIN
   -- no match, insert new value 
   INSERT INTO (...) VALUES (...);
END

请注意,由于竞争条件,这种方法很危险:没有什么可以防止另一个线程同时插入值,因此最终可能会出现重复或约束违规错误(最好是后者......)。

答案 1 :(得分:2)

这只是伪代码,因为我不知道你的表结构,但我想你会明白...基本上更新你想要的列然后插入你需要的列。光标操作听起来没必要。

Update OtherTable
  Set ColumnToIncrease = ColumnToIncrease + 1
FROM CurrentTable Where ColumnToCheckValue is not null

Insert Into OtherTable (ColumnToIncrease, Field1, Field2,...)
SELECT 
  1,
  ?
  ?
FROM CurrentTable Where ColumnToCheckValue is not null

答案 2 :(得分:2)

没有样品,我认为这是我能做的最好的。底线:您不需要光标。 UPDATE匹配存在(INNER JOIN)和INSERT,其中一个不匹配。

UPDATE otherTable
SET IncrementingColumn = IncrementingColumn + 1
FROM thisTable INNER JOIN otherTable ON thisTable.ID = otherTable.ID

INSERT INTO otherTable
(
   ID
   , IncrementingColumn
)
SELECT ID, 1
FROM thisTable
WHERE NOT EXISTS (SELECT *
                  FROM otherTable
                  WHERE thisTable.ID = otherTable.ID)

答案 3 :(得分:2)

我认为 you'd be better off using a view for this - 然后它总是最新的,没有错误的双重/三重/等计数的风险:

CREATE VIEW vw_value_count AS
  SELECT st.value,
         COUNT(*) AS numValue
    FROM SOME_TABLE st
GROUP BY st.value

但是如果您仍想使用INSERT / UPDATE方法:

IF EXISTS(SELECT NULL
            FROM SOMETABLE WHERE ... > 1) 
BEGIN
   UPDATE TABLE
      SET count = count + 1
    WHERE value = @value
END
ELSE
BEGIN
   INSERT INTO TABLE
     (value, count)
   VALUES
     (@value, 1)
END

答案 4 :(得分:1)

如何使用内连接执行+1的Update语句,并插入第一个表中不存在的选定行。

提供表格架构以及要检查和更新的列,以便我们提供帮助。

问候。

相关问题