什么是存儲過程
如果你接觸過其他的
編程語言,那么就好理解了,存儲過程就像是方法一樣。竟然他是方法那么他就有類似的方法名,方法要傳遞的變量和返回結果,所以存儲過程有存儲過程名有存儲過程參數也有返回值。
存儲過程的優點:
存儲過程的能力大大增強了SQL語言的功能和靈活性。
可保證數據的安全性和完整性。
通過存儲過程可以使沒有權限的用戶在控制之下間接地存取數據庫,從而保證數據的安全。
通過存儲過程可以使相關的動作在一起發生,從而可以維護數據庫的完整性。
在運行存儲過程前,數據庫已對其進行了語法和句法分析,並給出了優化執行方案。這種已經編譯好的過程可極大地改善SQL語句的性能。
可以降低網絡的通信量。
使體現企業規則的運算程序放入數據庫服務器中,以便 集中控制。
存儲過程可以分為系統存儲過程、擴展存儲過程和用戶自定義的存儲過程
系統存儲過程
我們先來看一下系統存儲過程,系統存儲過程由系統定義,主要存放在MASTER數據庫中,名稱以"SP"開頭或以"XP"開頭。盡管這些系統存儲過程在MASTER數據庫中,但我們在其他數據庫還是可以調用系統存儲過程。有一些系統存儲過程會在創建新的數據庫的時候被自動創建在當前數據庫中。 www.2cto.com
常用系統存儲過程有:
exec sp_databases; --查看數據庫
exec sp_tables; --查看表
exec sp_columns student;--查看列
exec sp_helpIndex student;--查看索引
exec sp_helpConstraint student;--約束
exec sp_helptext 'sp_stored_procedures';--查看存儲過程創建定義的語句
exec sp_stored_procedures;
exec sp_rename student, stuInfo;--更改表名
exec sp_renamedb myTempDB, myDB;--更改數據庫名稱
exec sp_defaultdb 'master', 'myDB';--更改登錄名的默認數據庫
exec sp_helpdb;--數據庫幫助,查詢數據庫信息
exec sp_helpdb master;
exec sp_attach_db --附加數據庫
exec sp_detach_db --分離數據庫
來看一下具體的代碼:
exec sp_databases
--查看有哪些數據庫
use MySchool
exec sp_tables
--可以看TABLE_OWNER字段顯示DBO里確認是用戶自己
exec sp_columns student
--除了用系統視圖可以查看列,用系統存儲過程也可以查看到列
exec sp_helpindex student
--查看索引,可以看到索引的描述,經過測試發現主鍵也是索種的一種
exec sp_helpconstraint student
--查看約束
exec sp_helptext 'sys.all_columns'
--查看系統視圖
exec sp_helptext 'sp_test'
--查看用戶自定義的存儲過程
exec sp_stored_procedures
--查看全部的存儲過程
exec sp_rename 'student','stuInfo'
--更改表名
use master
exec sp_renamedb 'myschool','school'
--更改數據庫名,為了更改成功,不能使用當前數據庫,需切換到其他數據庫
exec sp_rename N'student.idx_cid', N'idx_cidd', N'index';
--重命名索引
exec sp_helpdb
--數據庫幫助,查詢數據庫信息
--分離數據庫
use myschool
exec sp_detach_db 'test';
--exec sp_attach_db --附加數據庫
EXEC sp_attach_db @dbname = 'test',
@filename1 = 'D:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\test.mdf',
@filename2 = 'D:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\test_log.ldf'
www.2cto.com
用戶自定義存儲過程
在創建一個存儲過程前,先來說一下存儲過程的命名,看到好幾篇講存儲過程的文章都喜歡在創建存儲過程的時候加一個前綴,養成在存儲過程名前加前綴的習慣很重要,雖然這只是一件很小的事情,但是往往小細節決定大成敗。看到有的人喜歡這樣加前綴,例如proc_名字。也看到這加樣前綴usp_名字。前一種proc是procedure的簡寫,后一種sup意思是user procedure。我比較喜歡第一種,那么下面所有的存儲過程名都以第一種來寫。至於名字的寫法采用駱駝命名法。
創建存儲過程的語法如下:
CREATE PROC[EDURE] 存儲過程名
@參數1 [數據類型]=[默認值] [OUTPUT]
@參數2 [數據類型]=[默認值] [OUTPUT]
AS
SQL語句
EXEC 過程名[參數]
來看一下各種不同的存儲過程的實例:
45
--創建不帶參數的存儲過程
create procedure pro_student
as
select * from student;
--執行不帶參數的存儲過程
exec pro_student;
--修改不帶參數的存儲過程
alter procedure pro_student
as
select * from student where sid>3;
--執行修改后的存儲過程
exec pro_student;
--刪除存儲過程
drop procedure pro_student;
--創建帶輸出參數的存儲過程
create proc proc_getStudentRecord
(
@sex varchar(2) out, --輸出參數
@age int output--輸入輸出參數
) www.2cto.com
as
select * from student where ssex = @sex and sage = @age;
--不緩存在存儲過程
use myschool;
create procedure proc_recompileStudent
with recompile
as
select * from student
exec proc_recompileStudent
--
加密的存儲過程
create procedure proc_encrptStudent
with encryption
as
select * from student;
exec proc_recompileStudent
存儲過程返回值的方式
1、返回數字類型的存儲過程(還沒有想到返回字符串的方法)
IF exists(select * from sys.objects where name='proc_getScore0')
drop procedure proc_getScore0
GO
create procedure proc_getScore0
(
@id int
)
AS
BEGIN
declare @score int
select @score=english from Score where id=@id
IF(@score>60)
return 0
ELSE
return 1
END
--測試調用返回數字的存儲過程<br>declare @t int
EXEC @t = proc_getScore0 2
select @t;
--這里我遇到一個小問題,如果返回值是字符串,接收的時候declare @t nvarchar也出錯,那該怎么做?
--暫時沒有想到
2、返回變量的存儲過程
IF exists(select * from sys.objects where name='proc_getScore')
drop procedure proc_getScore
GO www.2cto.com
CREATE PROCEDURE proc_getScore
@id int,
@result varchar(50) output
AS
BEGIN
declare @score int
select @score=english from Score where id=@id
IF(@score>60)
set @result='及格'
ELSE
set @result='不及格'
END
GO
--測試一
declare @id int
declare @temp varchar(50)
set @id=3
exec proc_getScore @id,@temp output
select @temp
最后一個例子,用C#來調用具有返回值的存儲過程,這里我通過調用返回變量類型的存儲過程來做測試。測試在控件台下進行,以下寫了兩種方法,第二種更好,代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//方法一
//using (SqlConnection conn = new SqlConnection("server=.;database=myschool;uid=sa;pwd=123456"))
//{
// conn.Open();
// using (SqlCommand cmd = new SqlCommand("proc_getScore", conn))
// {
// cmd.CommandType = CommandType.StoredProcedure;
// cmd.Parameters.AddWithValue("@id", 2);
// SqlParameter sp = cmd.Parameters.Add("@result", SqlDbType.VarChar, 50); www.2cto.com
// sp.Direction = ParameterDirection.Output;
// cmd.ExecuteNonQuery();
// Console.Write(sp.Value);
// }
//}
//方法二
using (SqlConnection conn = new SqlConnection("server=.;database=myschool;uid=sa;pwd=123456"))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("proc_getScore", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter[] paras = {
new SqlParameter("@id",SqlDbType.Int),
new SqlParameter("@result",SqlDbType.NVarChar,50)
};
paras[0].Value = 2;
paras[1].Direction = ParameterDirection.Output;
cmd.Parameters.AddRange(paras);
cmd.ExecuteNonQuery();
Console.Write(paras[1].Value);
} www.2cto.com
}
Console.ReadLine();
}
}
}