存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编
译后存储在数据库中。存储过程可包含程序流、逻辑以及对数据库的查询。它
们可以接受参数、输出参数、返回单个或多个结果集以及返回值。
流程控制语句:
IF……ELSE
CASE
WHILE
WAITFOR
TRY/CATCH
1.IF……ELSE……
use pubs
declare @pic float
select @pic=sum(price) from titles
if @pic>500
begin
print 'more 500'
end
else
begin
print 'less 500'
end
2.Case 条件
when then
……
else
end
例子:
use northwind
go
select top 10 orderid,orderid %10 as 'Last Digit',Position=
Case orderid %10
when 1 then 'First'
when 2 then 'Second'
when 3 then 'Third'
when 4 then 'Fourth'
Else 'Something Else'
end
from orders
3.While循环
declare @i int
set @i=1
while @i<10
begin
print @i
set @i=@i+1
end
4.Waitfor等待后执行
Waitfor
Delay ‘01:00’ --等待一小时后执行
Print ‘SQL’
Waitfor
Time ’08:30’ --等待到8点30分执行操作
Print ‘SQL’
5.TRY……CATCH……例子
BEGIN TRY
SELECT 1/0;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO
下面我们创建一个带输出参数的存储过程:
use pubs
go
create procedure MyPRO
@id varchar(11),
@contract bit,
@phone char(12) output
as
select @phone=phone from authors where au_id=@id and [contract]
=@contract
--调用存储过程
exec mypro '267-41-2394',true,@phone output
print @phone
--修改存储过程
alter procedure mypro
as
select au_lname,au_fname from authors
--删除存储过程
drop proc Mypro
接下来我们创建一个加密的存储过程:
USE pubs
GO
Create PROCEDURE encrypt_this
--WITH ENCRYPTION
--对存储过程加密
with encryption
AS
Select *
FROM authors
GO
EXEC sp_helptext encrypt_this
加密之后再调用系统的sp_helptext去查询存储过程语句时会出现‘对象
'encrypt_this' 的文本已加密。’的提示。所以说存储过程加密用在不想让别人看到自己创建的存储过程语句时使用。
再举一个小例子:
CREATE PROCEDURE proc_stu
@notpassSum int OUTPUT,
@writtenPass int=60, //推荐将默认参数放后
@labPass int=60
AS
……
SELECT stuName,stuInfo.stuNo,writtenExam,
labExam FROM stuInfo INNER JOIN stuMarks
ON stuInfo.stuNo=stuMarks.stuNo
WHERE writtenExam<@writtenPass
OR labExam<@labPass
SELECT @notpassSum=COUNT(stuNo)
FROM stuMarks WHERE writtenExam<@writtenPass
OR labExam<@labPass
GO
/*---调用存储过程----*/
DECLARE @sum int
EXEC proc_stu @sum OUTPUT ,64
print '--------------------------------------------------'
IF @sum>=3
print '未通过人数:'+convert(varchar(5),@sum)+ '人,
超过60%,及格分数线还应下调'
ELSE
print '未通过人数:'+convert(varchar(5),@sum)+ '人,
已控制在60%以下,及格分数线适中'
GO
有一个实现新增功能的存储过程:
CREATE PROCEDURE AddNews
@title varchar(50),
@content text
AS
INSERT INTO NewsInfo(title,content,createdate) VALUES
(@title,@content,getdate())
RETURN 0
GO
如果我们要返回存储过程的返回值可以使用一下代码:
SqlConnection cnn = new SqlConnection();
cnn.ConnectionString = "Data Source = 数据
源;uid=sa;pwd = ;database=数据库名";
cnn.Open();//数据库连接
//设置存储过程参数
SqlParameter prm;
SqlCommand cmd = new SqlCommand();
cmd.Connection = cnn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "存储过程名";
//项目类型
prm = new SqlParameter();
prm.ParameterName = "参数名1";
prm.SqlDbType = SqlDbType.VarChar;
prm.Size = 50;
prm.Value = comboBox1.Text;
prm.Direction = ParameterDirection.Input;
cmd.Parameters.Add(prm);
...
//可以继续设置参数,参数个数由存储过程的具体内容决定
cmd.ExecuteNonQuery();//执行存储过程
实际上如果要获取存储过程的返回值,只要将上面一句代码修改成:
int retn = cmd.ExecuteNonQuery();
就可以了
通过调用存储过程不但能返回值,还能返回一张表,下面的代码中实现了创建一个临时表,并返回这个表(支持多个)的用法。希望对大家有帮助,这里还涉及到一个临时表的创建,什么是sql server真正的临时表,并发不冲突的临时表,要让系统建立在tempdb中才是,sql server会自动管理这些临时表。
在说之前先加点小知识:
当 SET QUOTED_IDENTIFIER 为 ON 时,标识符可以由双引号分隔,而文字必须由单引号分隔。当 SET QUOTED_IDENTIFIER 为 OFF 时,标识符不可加引号,且必须符合所有 Transact-SQL 标识符规则。当 SET ANSI_NULLS 为 ON 时,即使 column_name 中包含空值,使用 WHERE column_name = NULL 的 SELECT 语句仍返回零行。即使 column_name 中包含非空值,使用 WHERE column_name <> NULL 的 SELECT 语句仍会返回零行。 当 SET ANSI_NULLS 为 OFF 时,等于 (=) 和不等于 (<>) 比较运算符不遵从SQL-92 标准。使用 WHERE column_name = NULL 的 SELECT 语句返回column_name 中包含空值的行。使用WHEREcolumn_name <> NULL 的 SELECT语句返回列中包含非空值的行。此外,使用 WHERE column_name <>XYZ_value 的 SELECT 语句返回所有不为 XYZ_value 也不为 NULL 的行。
c#代码如下
DataSet ds = new DataSet();
System.Data.OleDb.OleDbCommand cmd =
m_TdlyDataAccess.DBConnection.CreateCommand();
cmd.CommandText = "prcTest";
cmd.CommandType = CommandType.StoredProcedure;
System.Data.OleDb.OleDbDataAdapter dap = new
System.Data.OleDb.OleDbDataAdapter(cmd);
dap.Fill(ds);
存储过程如下
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[prcTest]
AS
begin
CREATE TABLE #t(x INT PRIMARY KEY,y int default 0,z int default 0)
INSERT INTO #t VALUES (99,0,0)
INSERT INTO #t VALUES (239,0,0)
INSERT INTO #t VALUES (939,0,0)
select * from #t
drop table #t
end
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
存储过程分页:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[PROCE_SQL2005PAGECHANGE]
(
@TableName varchar(50), --表名
@ReFieldsStr varchar(200) = '*', --字段名(全部字段为*)
@OrderString varchar(200), --排序字段(必须!支持多字段不用加
order by)
@WhereString varchar(500) =N'', --条件语句(不用加where)
@PageSize int, --每页多少条记录
@PageIndex int = 1 , --指定当前为第几页
@TotalRecord int output --返回总记录数
)
AS
BEGIN
--处理开始点和结束点
Declare @StartRecord int;
Declare @EndRecord int;
Declare @TotalCountSql nvarchar(500);
Declare @SqlString nvarchar(2000);
set @StartRecord = (@PageIndex-1)*@PageSize + 1
set @EndRecord = @StartRecord + @PageSize - 1
SET @TotalCountSql= N'select @TotalRecord = count(*) from ' +
@TableName;--总记录数语句
SET @SqlString = N'(select row_number() over (order by '+
@OrderString +') as rowId,'+@ReFieldsStr+' from '+ @TableName;--查询
语句
--
IF (@WhereString! = '' or @WhereString!=null)
BEGIN
SET @TotalCountSql=@TotalCountSql + ' where '+
@WhereString;
SET @SqlString =@SqlString+ ' where '+ @WhereString;
END
--第一次执行得到
--IF(@TotalRecord is null)
-- BEGIN
EXEC sp_executesql @totalCountSql,N'@TotalRecord int
out',@TotalRecord output;--返回总记录数
-- END
----执行主语句
set @SqlString ='select * from ' + @SqlString + ') as t where
rowId between ' + ltrim(str(@StartRecord)) + ' and ' + ltrim(str
(@EndRecord));
Exec(@SqlString)
END
存储过程调用存储过程:
执行存储过程proc2,调用了存储过程proc1
create prco proc1
as
begin
print '被执行的存储过程proc1'
end
create proc proc2
as
begin
exec proc1
end
exec proc2
存储过程循环:
CREATE PROCEDURE AddStudents AS
Begin
Declare @n bigint
Declare @Sql nvarchar(225)
set @n=0
while @n<10000
begin
Set @Sql='Insert into Students Values
(''Hamunet'',10,''SianChina'',''123456789123'')'
Exec (@Sql)
set @n=@n+1
End