Получить инструкцию T-SQL CREATE для хранимых процедур SQLCLR - PullRequest
9 голосов
/ 09 ноября 2010

У меня есть приложение, которое извлекает текст хранимых процедур, используя sp_helptext .Он отлично работает на всех моих хранимых процедурах , за исключением для хранимых процедур CLR.Если я пытаюсь использовать sp_helptext в хранимой процедуре SQLCLR, я получаю эту ошибку:

Нет текста для объекта 'PROC_NAME'

Я знаю, что SSMS можетсделать это, когда я использую команду «script as» -> «create to» ->.

Но когда я отслеживаю действие «create script» SSMS с помощью SQL Server Profiler, он дает мне очень длинный списокдовольно сложная деятельность.Я могу пройти через это, если нужно, но кто-нибудь знает простой способ программно получить код хранимого процесса CLR?

Редактировать для уточнения
Я не хочуувидеть актуальный код из сборки;Я просто прошу простой способ просмотра кода T-SQL , как в этом примере:

CREATE PROCEDURE [dbo].[MY_PROC]
    @PARAM1 [xml],
    @PARAM2 [uniqueidentifier],
    @PARAM3 [nvarchar](255),
    @PARAM4[bit] = False
WITH EXECUTE AS OWNER
AS
EXTERNAL NAME [SomeSolution.SomeProject].[SomeAssembly].[SomeMethod]
GO

Другими словами, «сторона SQL Server» SQLCLRфункция.

Ответы [ 8 ]

3 голосов
/ 09 ноября 2010

Краткий ответ: нет, вы не можете этого сделать.(По крайней мере, не программно / легко) Процедуры CLR загружаются из сборок .NET (двоичные файлы), и не существует простого способа получить исходный код такого файла.Не в SQL Server.Но вы можете использовать такие инструменты, как RedGate Reflector , чтобы разобрать DLL и просмотреть / восстановить исходный код хранимой процедуры.

3 голосов
/ 09 ноября 2010

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

См. Основные понятия программирования интеграции CLR * , например

2 голосов
/ 24 июля 2012

У меня была одна и та же дилемма, и я снова и снова искал в Интернете любое решение, чтобы получить код хранимой процедуры CLR. Наконец-то пришлось ПРОФИЛЬировать, что действие SSMS «генерировать скрипт» сделало, как вы сказали, и вот что я получил:

--GET ALL CLR stored procedures
SELECT
sp.name AS [Name],
sp.object_id AS [object_ID],
case when amsp.object_id is null then N'''' else asmblsp.name end AS [AssemblyName],
case when amsp.object_id is null then N'''' else amsp.assembly_class end AS [ClassName],
case when amsp.object_id is null then N'''' else amsp.assembly_method end AS [MethodName]
FROM
sys.all_objects AS sp
LEFT OUTER JOIN sys.assembly_modules AS amsp ON amsp.object_id = sp.object_id
LEFT OUTER JOIN sys.assemblies AS asmblsp ON asmblsp.assembly_id = amsp.assembly_id
LEFT OUTER JOIN sys.procedures AS spp ON spp.object_id = sp.object_id
WHERE spp.type like 'PC'

--For each CLR SP get the parameters in use
SELECT
param.name AS [Name]
FROM
sys.all_objects AS sp
INNER JOIN sys.all_parameters AS param ON param.object_id=sp.object_id
WHERE sp.name like 'your_sp_name' order by param.parameter_id ASC

--For each parameter get the values, data type and so on...
SELECT
param.name AS [Name],
param.parameter_id AS [param_ID],
sp.object_id AS [object_ID],
param.default_value AS [DefaultValue],
usrt.name AS [DataType],
sparam.name AS [DataTypeSchema],
ISNULL(baset.name, N'''') AS [SystemType],
CAST(CASE WHEN baset.name IN (N'nchar', N'nvarchar') AND param.max_length <> -1 THEN         param.max_length/2 ELSE param.max_length END AS int) AS [Length],
CAST(param.precision AS int) AS [NumericPrecision],
CAST(param.scale AS int) AS [NumericScale]
FROM
sys.all_objects AS sp
INNER JOIN sys.all_parameters AS param ON param.object_id=sp.object_id
LEFT OUTER JOIN sys.types AS usrt ON usrt.user_type_id = param.user_type_id
LEFT OUTER JOIN sys.schemas AS sparam ON sparam.schema_id = usrt.schema_id
LEFT OUTER JOIN sys.types AS baset ON (baset.user_type_id = param.system_type_id and     baset.user_type_id = baset.system_type_id) 
WHERE param.name='@param1' and sp.name='your_sp_name'

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

1 голос
/ 08 апреля 2014

У нас была проблема изменений, которые не добавлялись в систему контроля версий, поэтому я сделал следующее, чтобы получить обновления.

  1. с помощью sqlservermanager я запросил все файлы sys.assembly_files в найти то, что мне было нужно.
  2. написал быструю консольную программу для получения исходного кода для файлов, которые были изменены.

    • В нашем случае это было для записей, имеющих Assembly_id 68541 и несколько файлов, все с file_id больше 3

    • источник для файла cs находится в столбце с именем content, а имя файла - в столбце с именем name. Я преобразовал содержимое в байтовый массив, а затем в строку и записал содержимое в текстовый файл, используя filename.txt.

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

      using (SqlConnection conn = new SqlConnection(connstring))
      {
          using (SqlCommand cmd = new SqlCommand("SELECT * FROM sys.assembly_files WHERE assembly_id = 68541 and file_id > 3", conn))
          {
              DataTable ds = new DataTable();
              using (SqlDataAdapter da = new SqlDataAdapter(cmd))
              {
                  da.Fill(ds);
                  foreach (DataRow r in ds.Rows)
                  {
                      byte[] binaryString = (byte[])r["content"];
                      string x = Encoding.UTF8.GetString(binaryString);
                      string filename = @"C:\SQLCLR";
                      string filePath = string.Format(@"{0}\{1}.txt", filename,r["name"]);
                      File.WriteAllText(filePath, x);
      
                  }
              }
          }
      }
      
1 голос
/ 24 февраля 2012

На самом деле, вы можете сделать это, проверив представление каталога sys.assembly_files:

SELECT CONVERT(VARCHAR(MAX), content) as my_source_code 
FROM sys.assembly_files
0 голосов
/ 06 февраля 2017
  1. В отличие от аналогичных объектов T-SQL, операторы CREATE [ STORED PROCEDURE | FUNCTION | TRIGGER | TYPE | AGGREGATE ] ... для объектов SQLCLR не сохраняются как есть; они получены через тип объекта и комбинацию sys.assemblies, sys.assembly_modules, sys.parameters, sys.types и sys.assembly_types.

    Если вы пытаетесь сконструировать эти операторы CREATE в T-SQL или другом языке, отличном от .NET, вам нужно выбрать соответствующие данные из этих таблиц и собрать их все воедино. Однако если вы используете .NET, вы можете использовать Scripter Class в библиотеке SMO ( Microsoft.SqlServer.Smo.dll ). Он должен быть в состоянии написать что-нибудь в SQL Server. И на самом деле, вам, вероятно, следует использовать его для сценариев всего для вашего инструмента вместо использования запросов.

  2. Помимо просмотра определений хранимых процедур / функций / триггеров на лету в SSMS (т. Е. Быстро и легко), вам не следует использовать sp_helptext для извлечения определений объектов. Он выполняет много ненужной работы, так как кажется, что он незначительно обновляется после SQL Server 2000. Две основные проблемы с ним:

    1. Он не обрабатывает отдельные строки длиной> 4000 символов
    2. Он допускает только новые строки CRLF (т. Е. \r\n), но не только новые строки LF (т. Е. \n), которые действительны.

    Вы можете увидеть это, просмотрев определение этой системной хранимой процедуры:

    EXEC sp_helptext 'sp_helptext';
    

    Вместо этого вы должны использовать либо встроенную функцию OBJECT_DEFINITION() (которая принимает object_id в качестве входных данных), либо выбрать один из представлений системного каталога, которые содержат следующие определения: sys.sql_modules, sys.server_sql_modules, sys.system_sql_modules и sys.system_sql_modules.

0 голосов
/ 28 июля 2014

Чтобы извлечь ассамблию, запустите:

DECLARE @IMG_PATH VARBINARY(MAX)
DECLARE @ObjectToken INT

SELECT @IMG_PATH = content FROM sys.assembly_files WHERE assembly_id = 65536

EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT
    EXEC sp_OASetProperty @ObjectToken, 'Type', 1
    EXEC sp_OAMethod @ObjectToken, 'Open'
    EXEC sp_OAMethod @ObjectToken, 'Write', NULL, @IMG_PATH
    EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL, 'D:\SqlServerProject1.dll', 2
    EXEC sp_OAMethod @ObjectToken, 'Close'
    EXEC sp_OADestroy @ObjectToken

Затем декомпилируйте его с помощью Redgate Reflector или любого .Net декомпилятора (ilspy, ...)

0 голосов
/ 25 сентября 2013

Это довольно просто - если у вас есть доступ к SQL Server Management Studio.

Щелкните правой кнопкой мыши хранимую процедуру CLR и выберите CREATE SCRIPT - voilla.

Happy CLRing.

-Danish.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...