版权声明: https://blog.csdn.net/ClearLoveQ/article/details/82787360
1.USE语句 设置当前数据库
2.声明变量 DECLARE @变量名 变量类型,@变量名 变量类型
可以用逗号分隔 也可以每个变量使用一次DECLARE
3.给变量赋值 SET 和 SELECT
当知道确切的值时,直接使用SET SET @test=10
当变量基于一个查询时,使用SELECT SELECT @test =MAX(age) FROM Employee
下面的和上面的效果一样,但是上面的更简洁:
4.AS其实是给参数赋值的
AS 存储过程语法的一部分,AS之前是存储过程参数和属性定义,AS后面表示存储过程内容的定义
5.Begin和end的作用:如果你的过程中有多条语句,那么你需要begin/end块。就一条语句,加不加就无所谓了
6.GO:GO 命令和 Transact-SQL语句不能在同一行中,但在GO命令行中可包含注释
7. 启用 ANSI_NULLS,所有与空值的比较运算结果为 UNKNOWN;否则空值与空值的比较结果为 TRUE。
启用 QUOTED_IDENTIFIER 表示使用双引号( "") 作为分隔符(当标示符不符合 SQL SERVER 的命名规则时可以使用 "" 或 [] 作为分隔符)
8.CAST的作用是用来构造语句的
9.讨论系统函数P195
9.1@@IDENTITY 返回最后一句运行语句的,自动生成的标识值
将@@IDENTITY传递到局部变量中,可以让我们将值保留以被输出给参考表使用
9.2@@ROWCOUNT 是反应有多少行受到影响
同样的,将@@ROWCOUNT传递到局部变量中,可以让我们将值保留以被输出给参考表使用
9.3同样的,当我们在使用一些函数的时候,最好将它的值传递给一个变量保存下来
10.批处理是T-SQL语句集合的逻辑单元,如果在语句解析时失败,则不运行;如果语句在运行时失败,那么知道语句发生错误之前所有语句将被执行。
每个批处理的错误不会阻止其他批处理的运行。
例子(1-9):
USE [SIPC]
GO
/****** Object: StoredProcedure [dbo].[ASelectDepartment] Script Date: 09/19/2018 14:59:55 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROC [dbo].[ASelectDepartment]
@Employee_Name nvarchar(100)=NULL,
@Dept_Name nvarchar(100)=NULL,
@Rowcount int=0
AS
SELECT @Dept_Name=(select Dept_Name from B_Department where Dept_Code=(select Dept_Code from B_Employee where Employee_Name=@Employee_Name))
SELECT @Dept_Name
BEGIN
IF @Dept_Name is NULL
select * from B_Department
ELSE
select * from B_Department
where Dept_Name=@Dept_Name
SELECT @Rowcount=@@ROWCOUNT
print N'受影响行数:'+CAST(@Rowcount as varchar(5))
PRINT N'部门名称是:'+@Dept_Name
END
GO
例子(10)
USE [SIPC]
GO
/****** Object: StoredProcedure [dbo].[ASelectEmployee] Script Date: 09/19/2018 15:14:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[ASelectEmployee]
@Employee_Name nvarchar(50)=NULL
AS
SET @Employee_Name='张三'
PRINT N'第一条批处理'+CAST(@Employee_Name as nvarchar(50))
GO
PRINT N'第二条批处理'+CAST(@Employee_Name as nvarchar(50))
GO
会报错:必须声明标量变量 "@Employee_Name",批处理独立发送到服务器,但是批处理之间如果有依赖关系,那么最起码错误后的语句将失败
11.GO是一个只被编辑工具识别的命令,表明结束当前批处理,服务器自己对于GO没有任何概念
12.批处理错误分为 语法错误 和 运行时错误
13.何时使用批处理?
这几个命令必须独自成批处理
CREATE DEFAULT
CREATE PROCEDURE
CREATE RULE
CREATE TRIGGER
CREATE VIEW
如果你删除一个对象,你可能需要把DROP语句作为一个批处理
14.SELECT TABLE_CATALOG FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='B_BANK' 查询表名为B_BANK的表在哪个数据库中
15.在新建一张表或者删除一张表时,前面加上USE 格外重要
16.使用批处理建立优先级
CREATE DATABASE TEST
GO --如果不加GO的话,会报错,说TEST 引用不存在,所以加上GO之后表明结束这个批处理
USE TEST
CREATE TABLE TestTable
(
name varchar(50),
age int
)
另外的
USE TEST
ALTER TABLE TestTable
ADD address varchar(100)
GO --此处不加GO,会报错列名 'address' 无效。
INSERT INTO TestTable
(name,age,address)
VALUES
('张三',20,'地址')
17.SQLCMD P201 但是SQLCMD返回的数据结果很不整齐,所以使用很少
18.动态执行EXEC|EXECUTE
USE [SIPC]
GO
/****** Object: StoredProcedure [dbo].[Aexec] Script Date: 09/19/2018 17:03:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[Aexec]
@deptsql nvarchar(500)=NULL
AS
SET @deptsql='DECLARE @deptname nvarchar(500)
SELECT @deptname=Dept_Name FROM B_Department where SN=141
Select @deptname AS "M"' --此处的别名不能是中文是为什么?
BEGIN
EXEC(@deptsql + 'AS "穆"') --此处就可以
END
注:EXEC中的变量@deptname生命周期在EXEC执行完之后结束
19.如果某个用户有存储过程的执行权限,但是没有某张表的执行权限,
那么如果此存储过程是一个简单的select语句查询,一切正常,
但是如果使用EXEC去执行一个select,将执行失败,原因是他没有防伪该表的权限
20.一个运行在存储过程,用户自定义函数,或者触发器中的EXEC语句的安全上下文,可以通过使用EXECUTE AS 子句而被覆盖
21.你不能在同一个语句中同时运行一个EXEC语句和函数,因为函数需要在EXEC所在行之前被解析,但是EXEC运行一个存储过程,有少数情况下合法
22.流控语句
X.1 IF...ELSE
IF <布尔表达式>
<SQL语句> |BEGIN <代码行> END
ELSE
<SQL语句> |BEGIN <代码行> END
注:当设置ANSI_NULLS 为ON时,NULL不等于任何东西 要使用is来代替=
但是你可以通过设置ANSI_NULLS 为OFF来改变这种状况,,强烈建议不这么做,因为这与ANSI标准相冲突
例子:
USE [SIPC]
GO
/****** Object: StoredProcedure [dbo].[AIF_ELSE] Script Date: 09/20/2018 09:37:25 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[AIF_ELSE]
AS
BEGIN
IF NOT EXISTS (
SELECT 'FOUND Tbale'+s.name+'.'+t.name
FROM sys.schemas s
JOIN sys.tables t
ON s.schema_id=t.schema_id
WHERE s.name='dbo'
AND t.name='AOurIFTest'
)
CREATE TABLE AOurIFTest(Coll int PRIMARY KEY)
ELSE
BEGIN
PRINT N'此表已经存在!'
INSERT INTO AOurIFTest VALUES(1);
END
END
GO
注:EXISTS是一个操作符,判断有没有;
sys是架构,当判断数据库中有没有一张表时,可以用上述的语句
X2. BEGIN ...END 代码块(上面的例子)
如果在一个IF ...ELSE中使用了BEGIN ...END 那么就应该在IF的每个代码块上都是用它,这是为了"保持一致",虽然并不必要,但是实践中这样做更好
X3.CASE语句
简单CASE:
CASE <输入表达式>
WHEN <when表达式> THEN <结果表达式>
[...n]
[ELSE <结果表达式>]
END
搜索CASE:
CASE
WHEN <布尔表达式> THEN <结果表达式>
[...n]
[ELSE <结果表达式>]
END
搜索CASE的强大之处在于,混合和匹配列表达式
简单CASE例子:
USE [SIPC]
GO
/****** Object: StoredProcedure [dbo].[ACASE] Script Date: 09/20/2018 10:10:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[ACASE]
AS
BEGIN
SELECT TOP 10 SN,SN%10 AS 'Last Digit',Position=
CASE SN%10
WHEN 0 THEN N'余数为0'
WHEN 1 THEN N'余数为1'
WHEN 2 THEN N'余数为2'
WHEN 3 THEN N'余数为3'
WHEN 4 THEN N'余数为4'
WHEN 5 THEN N'余数为5'
ELSE 'Something Else' --如果没有此ELSE,那么不匹配的那一列会为null
END
FROM B_Department
END
GO
--总之,只要你想在SQL语句任何分情况选择值的位置,都可以使用CASE
搜索CASE例子:
任何一个WHEN满足时就将终止,所以不需要break
USE [SIPC]
GO
/****** Object: StoredProcedure [dbo].[ACASE2] Script Date: 09/20/2018 10:37:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[ACASE2]
AS
BEGIN
SELECT TOP 10 SN,SN%10 AS N'余数',Dept_Name,position=
CASE
WHEN Dept_Name=N'法律合同部' THEN N'这是法律合同部' --注意在这里两部分都要添加N
WHEN SN%10<5 THEN N'余数小于5'
ELSE 'ELSE部分'
END
FROM B_Department
END
GO
注:此例子旨在说明when可以混合多列匹配
X3.WHILE循环
WHILE <布尔表达式>
<SQL语句>|
[BEGIN
<语句块>
[BREAK]
<SQL语句>|<语句块>
[CONTINUE]
END]
X4.WAITFOR语句
WAITFOR
DELAY <'时间> | TIME<'时间'>
注:可以设定等待时间量也可以设定确切的时间,
但是设定延迟只能设定小时,分钟,秒,不能指定天,最大延迟是24小时,
设定确定时间只能用24小时制的时间。
X4.TRY/CATCH块
BEGIN TRY
<SQL语句或语句块>
END TRY
BEGIN CATCH
<SQL语句>
END CATCH
错误级别:1-10:仅提示信息,这些不会触发CATCH块的执行。
11-19:相对严重的错误,可以捕获并优雅的退出。
20-25:非常严重,通常是系统错误,服务器端的代码无法知道是那种类型的错误,所以脚本和连接会立即的终止。
sys.messages
USE [SIPC]
GO
/****** Object: StoredProcedure [dbo].[ACreateTable] Script Date: 09/20/2018 14:13:54 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[ACreateTable]
AS
BEGIN
BEGIN TRY
CREATE TABLE AOurIFTest(Coll int PRIMARY KEY)
END TRY
BEGIN CATCH
DECLARE @ErrorNo INT,
@Severity tinyint,
@State smallint,
@LineNo int,
@Message nvarchar(4000)
SELECT @ErrorNo=ERROR_NUMBER() , --ERROR_NUMBER()实际的错误号
@Severity=ERROR_SEVERITY(), --ERROR_SEVERITY()错误级别
@State=ERROR_STATE() , --ERROR_STATE() 标识位,对于系统错误他总是1
@LineNo=ERROR_LINE() , --ERROR_LINE() 错误行号
@Message=ERROR_MESSAGE() --ERROR_MESSAGE()消息文本,对于系统消息,它同你从sys.message函数中选择的信息是一样的,对于用户自定义的错误,它会是由RAISERROR函数所提供的文本
IF @ErrorNo=2714
BEGIN
PRINT @Message
PRINT @ErrorNo
PRINT @Severity
PRINT @State
PRINT @LineNo
--PRINT N'此表已经存在'
END
ELSE
RAISERROR(@Message,16,6) --
END CATCH
END
GO
23.SQL SERVER显示行号: 工具/选项/文本编辑器 下的所有常规 设置行号勾选
总结:局部变量只在其所处的批中
有30多种系统函数,这里只介绍一些最有用的函数,系统函数不需要申明,总是可用