程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> SQL ServerCLR全功略之二---CLR存儲過程

SQL ServerCLR全功略之二---CLR存儲過程

編輯:關於SqlServer

從這一節開始呢,我們就要開始CLR的編程之旅了。在這之前,我先把本節中需要了解的兩個新類SqlDataRecord和SqlMetaData,及五個新方法SqlContext.Pipe.SendResultsStart,SqlContext.Pipe.SendResultsRow,SqlContext.Pipe.SendResultsEnd,SqlContext.Pipe.Send和SqlContext.Pipe.ExecuteAndSend進行一下必要的說明,方便大家閱讀後續的代碼。

首先SqlDataRecord和SqlMetaData是數據集合和原數據的意思。可以簡單的把SqlDataRecord理解成DataTable,把SqlMetaData理解成DataColumn。我們再向SqlDataRecord裡面填充數據之前要先執行SqlContext.Pipe.SendResultStart()方法,告訴數據庫下面開始填充數據,使用SqlContext.Pipe.SendResultRow方法來填充數據,填充結束後使用SqlContext.Pipe.SendResultEnd方法來結束填充。這些都是基本流程,沒什麼好解釋的,只要照著去做就可以了。

SqlContext.Pipe.Send是向客戶端發送一條結果,SqlContext.Pipe.ExecuteAndSend是執行一條語句。

下面我將用幾個實際的簡單例子來說明如何使用這幾個方法。

1.使用SqlContext.Pipe.Send構建無參無返回值的存儲過程
[Microsoft.SqlServer.Server.SqlProcedure]
public static void USP_SayHello()
{
    SqlContext.Pipe.Send("USP:Hello TJVictor!");
}

2.使用SqlContext.Pipe.Send構建帶參無返回值的存儲過程
[Microsoft.SqlServer.Server.SqlProcedure]
public static void USP_SayHelloByParameter(SqlString msg)
{
    SqlContext.Pipe.Send(msg.ToString());
}

3.使用SqlContext.Pipe.Send構建帶參有返回值的存儲過程
[Microsoft.SqlServer.Server.SqlProcedure]
public static SqlInt32 USP_SayHelloByReturn(SqlString msg)
{
    return msg.ToString().Length;
}

4.使用SqlCommand來執行語句,注意這裡使用了SQL Server自帶的pubs數據庫
[Microsoft.SqlServer.Server.SqlProcedure]
public static void USP_ExecuteBySqlCommand(SqlString stor_id, SqlString stor_name)
{
    //由於程序是在SQL Server內執行,所以連接字符串寫成"context connection=true"即可
    using (SqlConnection con = new SqlConnection("context connection=true"))
    {
        con.Open();
        SqlCommand com = new SqlCommand(
            string.Format("insert into stores values('{0}','{1}')", stor_id, stor_name), con);
        com.ExecuteNonQuery();
    }
}

5.使用ExecuteAndSend來執行語句,注意這裡使用了SQL Server自帶的pubs數據庫
[Microsoft.SqlServer.Server.SqlProcedure]
public static void USP_ExecuteByExecuteAndSend(SqlString stor_id, SqlString stor_name)
{
    //由於程序是在SQL Server內執行,所以連接字符串寫成"context connection=true"即可
    using (SqlConnection con = new SqlConnection("context connection=true"))
    {
        con.Open();
        SqlCommand com = new SqlCommand(
            string.Format("insert into stores values('{0}','{1}')", stor_id, stor_name), con);
        SqlContext.Pipe.ExecuteAndSend(com);
    }
}

4和5的執行結果一樣,但是在CLR中推薦使用方式5,這是將結果返回到客戶端的最高效方法,因為數據不必復制到托管內存即傳輸到網絡緩沖區。

6.使用PipeSend來發送單條記錄
[Microsoft.SqlServer.Server.SqlProcedure]
public static void UPS_PipeSendSqlDataRecord()
{
    //像構造Table一樣來構造SqlDataRecord,其中SqlMetaData類似DataColumn
    SqlDataRecord dataRecord = new SqlDataRecord(new SqlMetaData[] {
            new SqlMetaData("Col1", SqlDbType.NVarChar,100),
            new SqlMetaData("Col2", SqlDbType.Int)
                });
    for (int count = 1; count < 5; count++)
    {
        //SqlDataRecord.SetString類似DataRow的功能,像Table中填充值
        dataRecord.SetString(0, count.ToString());
        dataRecord.SetInt32(1, count);
        //通過Send來發送
        SqlContext.Pipe.Send(dataRecord);
    }
}

7.使用PipeSendResult來發送結果集
[Microsoft.SqlServer.Server.SqlProcedure]
public static void UPS_PipeSendResultSqlDataRecord()
{
    //像構造Table一樣來構造SqlDataRecord,其中SqlMetaData類似DataColumn
    SqlDataRecord dataRecord = new SqlDataRecord(new SqlMetaData[] {
            new SqlMetaData("Col1", SqlDbType.NVarChar,100),
            new SqlMetaData("Col2", SqlDbType.Int)
                });
    //開始填充
    SqlContext.Pipe.SendResultsStart(dataRecord);

    for (int count = 0; count < 5; count++)
    {
        //SqlDataRecord.SetString類似DataRow的功能,像Table中填充值
        dataRecord.SetString(0, count.ToString());
        dataRecord.SetInt32(1, count);
        //通過SendResultsRow把數據填充到Table,相關於Table.Rows.Add(DataRow);
        SqlContext.Pipe.SendResultsRow(dataRecord);
    }
    //填充結束,返回結果集
    SqlContext.Pipe.SendResultsEnd();
}

其中6與7的不同在於:6返回5個結果集,其中每個結果集只有一條數據。7返回一個結果集,裡面有5條數據。

最後說一下CLR存儲過程的部署:
Create proc 存儲過程名 as EXTERNAL NAME 數據庫中Assembly名稱.程序集中Assembly名稱.程序方法名。

注意,如果你的程序中有命名空間的話,要這樣寫:

Create proc 存儲過程名 as EXTERNAL NAME 數據庫中Assembly名稱.“程序命名空間.程序集中Assembly名稱”.程序方法名。

下面的SQL是創建CLR程序集和CLR存儲過程的SQL語句,假設我們編譯好的dll位於C:\CLRDemo.dll,我們的程序沒有命名空間(默認情況下,新建的SQL工程都沒有命名空間,請注意)
use pubs
go
create assembly CLRDemoAssemly
from 'c:\CLRDemo.dll'
go
create proc USP_SayHello as EXTERNAL NAME CLRDemoAssemly.StoredProcedures.USP_SayHello
go
create proc USP_SayHelloByParameter (@Msg nvarchar(128)) as EXTERNAL NAME CLRDemoAssemly.StoredProcedures.USP_SayHelloByParameter
go
create proc USP_SayHelloByReturn (@Msg nvarchar(128)) as EXTERNAL NAME CLRDemoAssemly.StoredProcedures.USP_SayHelloByReturn
go
create proc USP_ExecuteBySqlCommand (@Id nvarchar(4),@Name nvarchar(32)) as EXTERNAL NAME CLRDemoAssemly.StoredProcedures.USP_ExecuteBySqlCommand
go
create proc USP_ExecuteByExecuteAndSend (@Id nvarchar(4),@Name nvarchar(32)) as EXTERNAL NAME CLRDemoAssemly.StoredProcedures.USP_ExecuteByExecuteAndSend
go
create proc UPS_PipeSendSqlDataRecord as EXTERNAL NAME CLRDemoAssemly.StoredProcedures.UPS_PipeSendSqlDataRecord
go
create proc UPS_PipeSendResultSqlDataRecord as EXTERNAL NAME CLRDemoAssemly.StoredProcedures.UPS_PipeSendResultSqlDataRecord
go


調用方式:
exec USP_SayHello
go
exec USP_SayHelloByParameter 'Hello,TJVictor again'
go
declare @Result int
exec @Result=USP_SayHelloByReturn 'Hello,TJVictor again'
select @Result
go
exec USP_ExecuteBySqlCommand '1234','Test USP_ExecuteBySqlCommand'
go
exec USP_ExecuteByExecuteAndSend '5678','Test USP_ExecuteByExecuteAndSend'
go
exec UPS_PipeSendSqlDataRecord
go
exec UPS_PipeSendResultSqlDataRecord
go

刪除方式:注意刪除Assembly時,一定要先把引用此Assembly的所有東西刪除。
drop proc USP_SayHello
drop proc USP_SayHelloByParameter
drop proc USP_SayHelloByReturn
drop proc USP_ExecuteBySqlCommand
drop proc USP_ExecuteByExecuteAndSend
drop proc UPS_PipeSendSqlDataRecord
drop proc UPS_PipeSendResultSqlDataRecord
go
drop assembly CLRDemoAssemly

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved