Как оптимизировать этот запрос с помощью курсора? - PullRequest
0 голосов
/ 29 июня 2011
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

Выше приведен запрос для построения курсора, и он использует довольно много операций LIKE, NOT LIKE, которые, как я полагаю, могут быть дорогими для выполнения.

Поэтому я спрашиваю, есть ли лучший способ создать запрос, не используя слишком много LIKE/NOT LIKE и сделать его более оптимальным.

Спасибо.

РЕДАКТИРОВАТЬ:

Цель использования курсора здесь состоит в том, чтобы Loop Through все сопоставленные таблицы, чтобы мы могли динамически вставлять / обновлять / удалять записи.

В базе данных, которую я использую, содержится более 150 таблиц, поэтому я подумал, что sql server может также выполнить грязную работу.

1 Ответ

5 голосов
/ 29 июня 2011

Я бы:

1) сделал бы SQL более читабельным (IMO), используя NOT IN вместо нескольких "... и t.name <> ..."2) изменил c.name LIKEs на одно предложение 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 и выполняет его в одномgo (простой пример, если вы хотите вставить одну и ту же строку в каждую таблицу, каждая из которых имеет одинаковую структуру).Трудно знать, действительно ли это подходит для вашего точного сценария (или действительно ли это будет иметь смысл), но может быть полезно знать эту технику.

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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...