10

sp_helptextを使用してストアド プロシージャのテキストを取得するアプリケーションがあります。CLRストアドプロシージャを除くすべてのストアドプロシージャでうまく機能します。sp_helptextSQLCLR ストアド プロシージャで使用しようとすると、次のエラーが発生します。

オブジェクト「PROC_NAME」のテキストがありません

「script as」->「create to」->コマンドを使用すると、SSMSがそれを実行できることを私は知っています。

しかし、SSMS の "スクリプトの生成" アクションを SQL Server プロファイラーでトレースすると、非常に複雑なアクティビティの非常に長いリストが表示されます。必要に応じてそれをゆっくりと進めることができますが、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

つまり、SQLCLR 関数の「SQL Server 側」です。

4

9 に答える 9

3

私は同じジレンマを抱えており、CLR ストアド プロシージャのコードを取得するための解決策を Web で何度も検索しました。最後に、あなたが言ったように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 プログラマーではないので、その方法はわかりませんが、誰かが上記のクエリのプログラミングを行っている場合は、共有してください。

于 2012-07-24T16:27:38.900 に答える
2

CLR ストアド プロシージャには、DLL へのリンクなどのテキストはありません。DLL のソース コードを取得する必要があります。

たとえば、共通言語ランタイム (CLR) 統合プログラミングの概念を参照してください。

于 2010-11-09T16:48:01.370 に答える
2

簡単な答え: いいえ、それはできません。(少なくともプログラム/簡単ではありません) CLR プロシージャは .NET アセンブリ (バイナリ ファイル) から読み込まれ、そのようなファイルのソース コードを取得する簡単な方法はありません。SQL Server 内ではありません。ただし、 RedGate Reflectorなどのツールを使用して、DLL を逆アセンブルし、ストアド プロシージャのソース コードを表示/回復することができます。

于 2010-11-09T16:57:50.077 に答える
1

ソース管理に変更が追加されないという問題があったため、更新を取得するために次のことを行いました。

  1. sqlservermanager を使用して、すべての sys.assembly_files を照会して、必要なものを見つけました。
  2. 変更されたファイルのソースを取得するための簡単なコンソール プログラムを作成しました。

    • 私たちの場合、それは 68541 の assembly_id を持つレコードと、すべて 3 より大きい file_id を持つ複数のファイルのためのものでした

    • 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);
      
                  }
              }
          }
      }
      
于 2014-04-07T22:03:21.287 に答える
0

アセンブリを抽出するには、次を実行します。

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 など) で逆コンパイルします。

于 2014-07-28T09:31:44.417 に答える
0

実際には、これを行うことができます -sys.assembly_filesカタログ ビューを調べることによって:

SELECT CONVERT(VARCHAR(MAX), content) as my_source_code 
FROM sys.assembly_files
于 2012-02-24T18:04:12.937 に答える