Программно получить источник хранимой процедуры SQL Server, идентичный источнику, возвращенному графическим интерфейсом среды SQL Server Management Studio?


любые указатели на то, как я могу программно получить точно такой же источник хранимой процедуры из SQL Server 2005, как при щелчке правой кнопкой мыши на этой хранимой процедуре в среде SQL Server Management Studio и выборе modify?

Я пытаюсь использовать SMO, но есть некоторые текстовые различия. Процедура всегда имеет CREATE, а не ALTER, и есть некоторые различия в заголовке, такие как отсутствие GOs в версии, которую я получаю программно. Я могу это исправить, но, возможно, там это лучший способ?

опять же, я в SQL Server 2005, используя SMSE. Использование SMO через Visual Studio 8 2008.

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

пример: для sp_mysp щелкните правой кнопкой мыши в среде Management Studio и выберите Изменить. Это генерирует:

    USE [MY_DB]  
    GO  
    /****** Object:  StoredProcedure [dbo].[sp_mysp]    Script Date: 01/21/2009 17:43:18 ******/  
    SET ANSI_NULLS ON  
    GO  
    SET QUOTED_IDENTIFIER ON  
    GO  
    -- =============================================
    -- Author:      
    -- Create date: 
    -- Description: 
    -- =============================================
    ALTER PROCEDURE [dbo].[sp_mysp]

Я хочу программно получить то же самое (обратите внимание на GOs в заголовке, и тот факт, что это процедура ALTER. В идеале, я хотел бы получить это с минимальным программным исправлением извлеченного источника.

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

8 58

8 ответов:

EXEC sp_helptext 'your procedure name';

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

обновление: Дэвид пишет, что это не идентично его sproc...возможно, потому, что он возвращает строки как "записи" для сохранения форматирования? Если вы хотите увидеть результаты в более "естественном" формате, вы можете сначала использовать Ctrl-T (вывод в виде текста), и он должен распечатать его точно так же, как вы его ввели. Если вы делаете это в коде, это тривиально сделайте foreach, чтобы собрать ваши результаты точно так же.

Update 2: это предоставит источнику "создать процедуру", а не "изменить процедуру", но я не знаю, как заставить его использовать "ALTER" вместо этого. Но ведь это тривиальная вещь, не так ли?

обновление 3: см. комментарии для получения дополнительной информации о том, как поддерживать SQL DDL (структура базы данных) в системе управления версиями. Это действительно ключ к этому вопросу.

вам придется передать код, SQL Profiler показывает следующее.

SMSE выполняет довольно длинную строку запросов, когда он генерирует инструкцию.

следующий запрос (или что-то вдоль линий) используется для извлечения текста:

SELECT
NULL AS [Text],
ISNULL(smsp.definition, ssmsp.definition) AS [Definition]
FROM
sys.all_objects AS sp
LEFT OUTER JOIN sys.sql_modules AS smsp ON smsp.object_id = sp.object_id
LEFT OUTER JOIN sys.system_sql_modules AS ssmsp ON ssmsp.object_id = sp.object_id
WHERE
(sp.type = N'P' OR sp.type = N'RF' OR sp.type='PC')and(sp.name=N'#test___________________________________________________________________________________________________________________00003EE1' and SCHEMA_NAME(sp.schema_id)=N'dbo')

он возвращает чистое создание, которое затем заменяется на ALTER в коде где-то.

набор ANSI NULL вещи и GO операторы и даты все добавляются к этот.

перейти с sp_helptext, его проще ...

вы сказали программно, верно? Я надеюсь, что C# в порядке. Я знаю, что вы сказали, что попробовали SMO, и он не совсем сделал то, что вы хотели, поэтому это, вероятно, не будет идеально подходит для вашего запроса, но он будет программно считывать законные инструкции SQL, которые вы можете запустить, чтобы воссоздать хранимую процедуру. Если у него нет GO операторы, которые вы хотите, вы, вероятно, можете предположить, что каждая из строк в StringCollection может быть GO после него. Вы не можете получить этот комментарий с датой и время в нем, но в моем аналогичном проекте звучания (инструмент развертывания big-ass, который должен создавать резервные копии всего по отдельности), это сделано довольно хорошо. Если у вас есть предыдущая база, с которой вы хотели работать, и у вас все еще есть исходная база данных для запуска этого, я бы подумал о том, чтобы бросить начальные усилия и обновить этот вывод.

using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
…
string connectionString = … /* some connection string */;
ServerConnection sc = new ServerConnection(connectionString);
Server s = new Server(connection);
Database db = new Database(s, … /* database name */);
StoredProcedure sp = new StoredProcedure(db, … /* stored procedure name */);
StringCollection statements = sp.Script;

используйте следующую инструкцию select, чтобы получить все определение целиком:

select ROUTINE_DEFINITION from INFORMATION_SCHEMA.ROUTINES Where ROUTINE_NAME='someprocname'

Я предполагаю, что SSMS и другие инструменты считывают это и при необходимости вносят изменения, такие как изменение CREATE to ALTER. Насколько я знаю, SQL хранит не другие представления процедуры

Я согласен с Марком. Я установил вывод в текстовый режим, а затем sp_HelpText 'sproc'. Я привязал это к Crtl-F1, чтобы сделать его легким.

The Мастер Публикации Базы Данных можете сбросить схему (и другие объекты) из командной строки.

Я просто хочу отметить, что вместо того, чтобы использовать find и replace для изменения процедуры create для изменения процедуры, вы также можете использовать drop, вы можете поместить его прямо вверху, и он требует текстового поиска.

IF exists (SELECT * FROM sys.objects 
        WHERE object_id = OBJECT_ID(N'sp_name')
            and type in ('P','V') --procedure or view
        )
    DROP sp_name
GO

Если вы уверены, что он там, я думаю, вы могли бы просто бросить его тоже, но я бы не рекомендовал этого. Не забывайте о go, так как процедура create должна быть первой и единственной инструкцией в пакете.

или ленивый подход:

IF OBJECT_ID(N'sp_name') is not null
    DROP sp_name
GO

чтобы изменить хранимую процедуру, вот код C#:

SqlConnection con = new SqlConnection("your connection string");
con.Open();
cmd.CommandType = System.Data.CommandType.Text;
string sql = File.ReadAllText(YUOR_SP_SCRIPT_FILENAME);
cmd.CommandText = sql;   
cmd.Connection = con;
cmd.ExecuteNonQuery();
con.Close();

Примечание:

  1. убедитесь, что пользователь в строке подключения имеет право изменять SP
  2. удалить все GO,SET ANSI_NULLS XX,SET QUOTED_IDENTIFIER инструкции из файла сценария. (Если вы этого не сделаете, SqlCommand выдаст ошибку).