如何使用游标优化此查询?

时间:2011-06-29 07:33:45

标签: sql sql-server tsql optimization stored-procedures

DECLARE tableList CURSOR FOR    
    SELECT  t.name 
    FROM sys.tables t
        INNER JOIN sys.columns c
        ON t.object_id = c.object_id
    WHERE
            t.name NOT LIKE 'z%'
        AND t.name NOT LIKE '%delete%'
        AND t.name <> 'tblUsers'
        AND t.name <> 'tblUserLogins'
        AND t.name <> 'searchR'
        AND t.name <> 'tblUserPortfolio'
        AND t.name <> 'alerts_User'
        AND c.name LIKE 'userid'
        OR  c.name LIKE 'user_id'
    ORDER BY name
OPEN tableList
FETCH NEXT FROM tableList
INTO @tablename

上面是构建游标的查询,它使用了很多LIKENOT LIKE个操作,我认为这些操作可能很昂贵。

所以我问是否有更好的方法来构建查询而不使用太多LIKE/NOT LIKE并使其更优化。

感谢。

编辑:

此处使用游标的目的是Loop Through所有匹配的表,以便我们可以动态插入/更新/删除记录。

我正在使用的数据库中有超过150个表,所以我认为sql server也可以做脏工作。

1 个答案:

答案 0 :(得分:5)

我会:

1)使用NOT IN代替多个“...和t.name&lt;&gt; ...”,使SQL更具可读性(IMO) 2)将c.name LIKE更改为单个IN子句,因为您似乎想要完全匹配,不需要LIKE

SELECT  t.name 
FROM sys.tables t
    INNER JOIN sys.columns c ON t.object_id = c.object_id
WHERE t.name NOT LIKE 'z%' AND t.name NOT LIKE  '%delete%' 
    AND t.name NOT IN  ('tblUsers','tblUserLogins','searchR','tblUserPortfolio','alerts_User')
    AND c.name IN ('userid','user_id') 
ORDER BY name

这实际上不太可能在性能方面做出很多不同,但我认为它使其更具可读性/可维护性。

但是,我要提出的要点是你是否真的需要一个光标 - 我绝对希望将其删除,而采用基于集合的方法。虽然需要知道你在光标中做了什么,以便提出一个替代方案。

修改 您可以尝试这种动态生成SQL并一次执行它的方法(简单示例,假设您希望将相同的行插入到每个具有相同结构的表中)。很难知道这是否真的适合你的确切场景(或者它是否真的会产生有价值的差异),但知道这种技术会很有用。

DECLARE @nSQL NVARCHAR(MAX)
SELECT @nSQL = COALESCE(@nSQL, '')  + 
'INSERT ' + QUOTENAME(t.name) + '([SomeCol]) VALUES (@ValueToInsert);' + CHAR(10)
FROM sys.tables t
    INNER JOIN sys.columns c ON....
...{rest of current SELECT)

-- comment out PRINT, and uncomment EXECUTE statement to actually run the SQL
PRINT @nSQL
-- EXECUTE sp_executesql @nSQL, N'@ValueToInsert VARCHAR(10)', 'NewValue'