2009-07-24 4 views
16

Я хочу, чтобы все хранимые процедуры все еще синтаксически действовали. (Это может произойти, если кто-то переименовывает/удаляет таблицу/столбец).Синтаксис проверяет все хранимые процедуры?

Сейчас мое решение, чтобы проверить синтаксис всех хранимых процедур, чтобы войти в Enterprise Manager, выберите первую хранимую процедуру в списке, и использовать процедуру:

  1. Введите
  2. Alt + C
  3. побег
  4. побег
  5. Стрелка вниз
  6. Goto 1

Это работает, но это довольно утомительно. я хотел бы хранимую процедуру, которая называется

SyntaxCheckAllStoredProcedures

как другой хранимой процедуры я написал, что делает то же самое для просмотров:

RefreshAllViews


Для каждого человека выгоды, RefreshAllViews:

RefreshAllViews.prc

CREATE PROCEDURE dbo.RefreshAllViews AS 

-- This sp will refresh all views in the catalog. 
--  It enumerates all views, and runs sp_refreshview for each of them 

DECLARE abc CURSOR FOR 
    SELECT TABLE_NAME AS ViewName 
    FROM INFORMATION_SCHEMA.VIEWS 
OPEN abc 

DECLARE @ViewName varchar(128) 

-- Build select string 
DECLARE @SQLString nvarchar(2048) 

FETCH NEXT FROM abc 
INTO @ViewName 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @SQLString = 'EXECUTE sp_RefreshView '[email protected] 
    PRINT @SQLString 
    EXECUTE sp_ExecuteSQL @SQLString 

    FETCH NEXT FROM abc 
    INTO @ViewName 
END 
CLOSE abc 
DEALLOCATE abc 

на благо каждого, хранимую процедуру, чтобы пометить все хранимую процедуру в качестве нуждающихся перекомпилировать (маркировка хранимой процедуры для перекомпиляции не скажет вам, если это синтаксически действует):

RecompileAllStoredProcedures.prc

CREATE PROCEDURE dbo.RecompileAllStoredProcedures AS 

DECLARE abc CURSOR FOR 
    SELECT ROUTINE_NAME 
    FROM INFORMATION_SCHEMA.routines 
    WHERE ROUTINE_TYPE = 'PROCEDURE' 
OPEN abc 

DECLARE @RoutineName varchar(128) 

-- Build select string once 
DECLARE @SQLString nvarchar(2048) 

FETCH NEXT FROM abc 
INTO @RoutineName 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @SQLString = 'EXECUTE sp_recompile '[email protected] 
    PRINT @SQLString 
    EXECUTE sp_ExecuteSQL @SQLString 

    FETCH NEXT FROM abc 
    INTO @RoutineName 
END 
CLOSE abc 
DEALLOCATE abc 

Для полноты, UpdateAllStatistics процедура. Это обновит все статистические данные в базе данных, выполнив полную проверку данных:

RefreshAllStatistics.prc

CREATE PROCEDURE dbo.RefreshAllStatistics AS 

EXECUTE sp_msForEachTable 'UPDATE STATISTICS ? WITH FULLSCAN' 
+0

Посмотрите ваши пометки. Это был единственный вопрос на сайте с меткой «sqlserver». Вместо этого используйте 'sql-server'. –

ответ

1

Кроме того, вы можете рассмотреть вопрос об использовании Visual Studio Team System 2008 Database Edition, которые, помимо всего прочего, делает статическую проверку всех хранимых процедур в проекте по сборке, гарантируя тем самым, что все согласуются с текущей схемой.

+0

Это работает только, я полагаю, если вы работаете в Visual Studio или с базой данных SQL Server 2008? –

+0

@ Я знаю, что он работает только с визуальной студией, так как он будет использовать конкретный тип проекта базы данных (точнее, вам нужна VS Team System), но он работает с Sql Server 2005 также – Aleris

0

Немного затяжного варианта:

  1. Создать копию базы данных (резервное копирование и восстановление). Вы можете сделать это в целевой базе данных, если ваш уровень доверия высок.
  2. Используйте SSMS в сценарий из всех хранимых процедур в один файл сценария
  3. DROP все процедуры
  4. Запустите сценарий, чтобы воссоздать их. Любой, который не может быть создан, выйдет из строя.

Пара суетливых подводных камней здесь, таких как:

  • Вы хотите иметь «если прок существует то падение прок GO создать процедурный ... GO» синтаксис separte каждую процедуру.
  • Вложенные процедуры потерпят неудачу, если они вызывают процесс, который еще не был (re). Запуск сценария несколько раз должен поймать, что (с их правильное оформление может быть реальной болью ).
  • Другие и более неясные проблемы могут возникнуть, поэтому будьте осторожны.

Чтобы быстро отказаться от 10 или 1000 процедур, запустите

SELECT 'DROP PROCEDURE ' + schema_name(schema_id) + '.' + name 
from sys.procedures 

выбрать выход, и запустить его.

Предполагается, что вы выполняете очень нечастую задачу. Если вам нужно делать это регулярно (ежедневно, еженедельно ...), пожалуйста, сообщите почему!

+0

Да, я не отказываюсь от хранимых процедур на базе данных в реальном времени;) –

0

Невозможно сделать это с помощью T-SQL или Enterprise Manager, поэтому мне пришлось написать что-то из кода клиента. я не буду размещать весь код здесь, но хитрость заключается в том, чтобы:

1) Получить список всех хранимых процедур

SELECT ROUTINE_NAME AS StoredProcedureName 
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE ROUTINE_TYPE = 'PROCEDURE' --as opposed to a function 
ORDER BY ROUTINE_NAME 

2) Получить хранимую процедуру создания T-SQL:

select 
    c.text 
from dbo.syscomments c 
where c.id = object_id(N'StoredProcedureName') 
order by c.number, c.colid 
option(robust plan) 

3) Запуск создать заявление с поехесом на, так что синтаксис проверяется, но не на самом деле пытается создать хранимую процедуру:

connection("SET NOEXEC ON", ExecuteNoRecords); 
connection(StoredProcedureCreateSQL, ExecuteNoRecords); 
connection("SET NOEXEC ON", ExecuteNoRecords); 
+1

Решила принять вашу задачу: D не уверен, что нам разрешено самостоятельно подключать блоги, но я опубликовал полное решение в своем блоге. Оказалось, было тихо. [ссылка] (http://chocosmith.wordpress.com/2012/12/07/tsql-recompile-all-views-and-stored-proceedures-and-check-for-error/) Я еще не проверил против таблицы обрезания, хотя я вижу, что это проблема. Я не думаю, что студия управления тоже исправляет это. –

7

Вы также можете сделать это «на месте» - без получения всех операторов создания.

В дополнение к настройке NOEXEC ON, вам также необходимо установить свой любимый SHOWPLAN_* ON (я использую SHOWPLAN_TEXT). Теперь вы можете избавиться от своего шага 2 и просто выполнить каждую процедуру, которую вы получили на этапе 1.

Вот пример с использованием индивидуальной хранимой процедуры. Вы можете вставить его в своем любимом цикле:

create procedure tests @bob int as 
select * from missing_table_or_view 
go 

set showplan_text on; 
go 

set noexec on 

exec tests 

set noexec off 
go 
set showplan_XML off 
go 
drop procedure tests 
go 

Приведенный выше пример должен генерировать следующий вывод:

Msg 208, уровень 16, состояние 1, процедура испытаний, линия 2
недопустимое имя объекта 'missing_table_or_view.

1

Я знаю, что это старый способ, но я создал немного другую версию, которая на самом деле повторно создает все хранимые процедуры, тем самым бросая ошибки, если они не могут скомпилироваться. Этого не достигается с помощью команды SP_Recompile.

CREATE PROCEDURE dbo.UTL_ForceSPRecompilation 
(
    @Verbose BIT = 0 
) 
AS 
BEGIN 

    --Forces all stored procedures to recompile, thereby checking syntax validity. 

    DECLARE @SQL NVARCHAR(MAX) 
    DECLARE @SPName NVARCHAR(255)   

    DECLARE abc CURSOR FOR 
     SELECT NAME, OBJECT_DEFINITION(o.[object_id]) 
     FROM sys.objects AS o 
     WHERE o.[type] = 'P' 
     ORDER BY o.[name] 

    OPEN abc 

    FETCH NEXT FROM abc 
    INTO @SPName, @SQL 
    WHILE @@FETCH_STATUS = 0 
    BEGIN  

     --This changes "CREATE PROCEDURE" to "ALTER PROCEDURE" 
     SET @SQL = 'ALTER ' + RIGHT(@SQL, LEN(@SQL) - (CHARINDEX('CREATE', @SQL) + 6)) 

     IF @Verbose <> 0 PRINT @SPName 

     EXEC(@SQL) 

     FETCH NEXT FROM abc 
     INTO @SPName, @SQL 
    END 
    CLOSE abc 
    DEALLOCATE abc 

END 
+0

Работает нормально, но нужно обрабатывать 'CREATE PROC' тоже –

3

Если вы используете SQL Server 2008 R2 или ниже не используйте

SET поехес ON

Он проверяет только синтаксис и не для потенциальных ошибок, таких как наличие таблиц или столбцов. Вместо использование:

SET FMTONLY ON

он будет делать полные компиляции, поскольку он пытается вернуть метаданные хранимой процедуры.

В 2012 и вам нужно будет использовать хранимую процедуру: sp_describe_first_result_set

Также вы можете сделать полный скрипт в TSQL, который проверяет все зр и взгляды, его только немного работы.

UPDATE Я написал полное решение для tsql, которое проходит через все пользовательские сохраненные процедуры и проверяет там синтаксис. скрипт долго наматывается, но можно найти здесь http://chocosmith.wordpress.com/2012/12/07/tsql-recompile-all-views-and-stored-proceedures-and-check-for-error/

+0

Кто-нибудь пробовал' SET FMTONLY ON' (или 'sp_describe_first_result_set') с' TRUNCATE TABLE CustomerAccounts'? –

+2

@ChocoSmith Для ** хранимых процедур **, существует ли недостаток использования sys.sp_refreshsqlmodule? Я обнаружил, что он поймает хранимые процедуры, которые не соответствуют таблицам или изменениям схемы. – Question3CPO

+0

@ Question3CPO Превосходный catch/point, fmtonly проверит базовую схему, но sp_refreshsqlmodule проверит текущую схему. sp_refreshsqlmodule также будет работать против представлений (это то же самое, что вызывать sp_refreshview на представлениях). sp_refreshsqlmodule немного медленнее, но я не думаю, что скорость должна вызывать беспокойство, когда дело доходит до разбитых хранимых процедур :). Я проверю его сегодня вечером и посмотрю, что обновление ничего не сломает. –

0

Вот поправка, которая имеет дело с несколькими схемами

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[RefreshAllViews] AS 

-- This sp will refresh all views in the catalog. 
--  It enumerates all views, and runs sp_refreshview for each of them 

DECLARE abc CURSOR FOR 
    SELECT TABLE_SCHEMA+'.'+TABLE_NAME AS ViewName 
    FROM INFORMATION_SCHEMA.VIEWS 
OPEN abc 

DECLARE @ViewName varchar(128) 

-- Build select string 
DECLARE @SQLString nvarchar(2048) 

FETCH NEXT FROM abc 
INTO @ViewName 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @SQLString = 'EXECUTE sp_RefreshView ['[email protected]+']' 
    PRINT @SQLString 
    EXECUTE sp_ExecuteSQL @SQLString 

    FETCH NEXT FROM abc 
    INTO @ViewName 
END 
CLOSE abc 
DEALLOCATE abc 
GO 
0

Я знаю, что это старый вопрос, но это мое решение, когда я не мог найти устраивающие ,

Мне нужно проверить мои хранимые процедуры и представления после многих изменений в базе данных.

В основном я хотел попробовать выполнить ALTER PROCEDURE и ALTER VIEW с использованием текущих процедур и представления (фактически не изменяя их).

Я написал это, что работает достаточно хорошо.

Примечание! Не выполняйте работу в живой базе данных, создайте копию для проверки, а затем исправьте все, что нужно для исправления. Также sys.sql_modules могут быть непоследовательными, поэтому проявляйте особую осторожность. Я не использую это, чтобы на самом деле внести изменения, только чтобы проверить, какие из них не работают должным образом.

DECLARE @scripts TABLE 
(
    Name NVARCHAR(MAX), 
    Command NVARCHAR(MAX), 
    [Type] NVARCHAR(1) 
) 

DECLARE @name NVARCHAR(MAX),  -- Name of procedure or view 
    @command NVARCHAR(MAX),   -- Command or part of command stored in syscomments 
    @type NVARCHAR(1)    -- Procedure or view 

INSERT INTO @scripts(Name, Command, [Type]) 
SELECT P.name, M.definition, 'P' FROM sys.procedures P 
JOIN sys.sql_modules M ON P.object_id = M.object_id 

INSERT INTO @scripts(Name, Command, [Type]) 
SELECT V.name, M.definition, 'V' FROM sys.views V 
JOIN sys.sql_modules M ON V.object_id = M.object_id 

DECLARE curs CURSOR FOR 
SELECT Name, Command, [Type] FROM @scripts 

OPEN curs 

FETCH NEXT FROM curs 
INTO @name, @command, @type 


WHILE @@FETCH_STATUS = 0 
BEGIN 
    BEGIN TRY 
     IF @type = 'P' 
      SET @command = REPLACE(@command, 'CREATE PROCEDURE', 'ALTER PROCEDURE') 
     ELSE 
      SET @command = REPLACE(@command, 'CREATE VIEW', 'ALTER VIEW') 


     EXEC sp_executesql @command 
     PRINT @name + ' - OK' 
    END TRY 
    BEGIN CATCH 
     PRINT @name + ' - FAILED: ' + CAST(ERROR_NUMBER() AS NVARCHAR(MAX)) + ' ' + ERROR_MESSAGE() 
     --PRINT @command 
    END CATCH 

    FETCH NEXT FROM curs 
    INTO @name, @command, @type 
END 

CLOSE curs 
2

Проверку предложенных KenJ, безусловно, лучший вариант, так как воссоздавать/альтер подходы не найти все ошибки. Например.

  • невыполнимых планы выполнения из-за запросы подсказки
  • У меня даже был SP, ссылающейся на несуществующую таблицу, которая прошла через без обнаружения ошибки.

Пожалуйста, найдите мою версию, которая проверяет все существующие SP одновременно с помощью метода KenJ. AFAIK, он обнаружит каждую ошибку, которая будет препятствовать выполнению SP.

--Forces the creation of execution-plans for all sps. 
--To achieve this, a temporary SP is created that calls all existing SPs. 
--It seems like the simulation of the parameters is not necessary. That makes things a lot easier. 
DECLARE @stmt NVARCHAR(MAX) = 'CREATE PROCEDURE pTempCompileTest AS ' + CHAR(13) + CHAR(10) 
SELECT @stmt = @stmt + 'EXEC [' + schemas.name + '].[' + procedures.name + '];' 
    FROM sys.procedures 
     INNER JOIN sys.schemas ON schemas.schema_id = procedures.schema_id 
    WHERE schemas.name = 'dbo' 
    ORDER BY procedures.name 

EXEC sp_executesql @stmt 
GO 

--Here, the real magic happens. 
--In order to display as many errors as possible, XACT_ABORT is turned off. 
--Unfortunately, for some errors, the execution stops anyway. 
SET XACT_ABORT OFF 
GO 
--Showplan disables the actual execution, but forces t-sql to create execution-plans for every statement. 
--This is the core of the whole thing! 
SET SHOWPLAN_ALL ON 
GO 
--You cannot use dynamic SQL in here, since sp_executesql will not be executed, but only show the string passed in in the execution-plan 
EXEC pTempCompileTest 
GO 
SET SHOWPLAN_ALL OFF 
GO 
SET XACT_ABORT ON 
GO 
--drop temp sp again 
DROP PROCEDURE pTempCompileTest 
--If you have any errors in the messages-window now, you should fix these... 
Смежные вопросы