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

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

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

Опять же, я в 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]

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

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

Ответы [ 8 ]

80 голосов
/ 22 января 2009
EXEC sp_helptext 'your procedure name';

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

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

Обновление 2: это обеспечит источник «CREATE PROCEDURE», а не «ALTER PROCEDURE», но я не знаю способа заставить его использовать «ALTER» вместо этого. Впрочем, это довольно банально, не правда ли?

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

15 голосов
/ 22 января 2009

Вам придется написать код, 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')

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

К этому добавлены элементы SET ANSI NULL, а также операторы и даты GO.

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

11 голосов
/ 02 июня 2009

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

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;
7 голосов
/ 22 января 2009

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

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

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

5 голосов
/ 22 января 2009

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

4 голосов
/ 22 января 2009
2 голосов
/ 03 февраля 2012

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

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

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

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

IF OBJECT_ID(N'sp_name') is not null
    DROP sp_name
GO
0 голосов
/ 18 марта 2010

Чтобы изменить хранимую процедуру, вот код 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 выдаст ошибку).
...