使用SQL SERVER需要注意的一些细节
养成写注释的习惯。比如存储过程,我们不仅在创建存储过程的时候写注释,而且是以后的开发版本中修改了存储过程,那么也要写注释。
存储过程不要以sp_开头,因为系统存储过程都是以sp_开头的。
而且在执行sp_开关的存储过程时数据库引擎首先在master数据库中查找这个存储过程,如果找不到,再去其它数据库查找。
-- 创建一个sp_开头的存储过程
IF OBJECT_ID('[dbo].[sp_executesql]') IS NOT NULL
DROP PROCEDURE [dbo].[sp_executesql];
CREATE PROC [dbo].[sp_executesql]
AS
SELECT 1 AS [ID];
GO
-- 这样调用的其实是系统存储过程(sys架构下)
EXEC [dbo].[sp_executesql];
存储过程内部尽量用静态语句书写,避免用字符串拼凑执行,避免不了时可能用sp_executesql。
-- 拼凑字符串形式的语句,执行计划不会重用
DECLARE @s VARCHAR(500);
SET @s = '
SELECT * FROM dbo.T_Product WHERE ProductId = '
+ LTRIM(@product_id);
EXEC(@s);
-- 使用动态参数批的sp_executesql,执行计划可以重用
DECLARE @s NVARCHAR(500);
DECLARE @parameters NVARCHAR(200);
SET @parameters = N'@p_product_id INT';
SET @s = '
SELECT * FROM test.dbo.T_Product WHERE ProductId = @p_product_id';
EXEC sp_executesql @s,@parameters,@p_product_id = @product_id;
每一个T-SQL语句的编写要以分号结束。
据说在以后的数据库版本里面会强制要求。现在的版本,在公用表过式的编写中,就有这个限制。
-- 语句没有以分号结束
SELECT * FROM dbo.t_product WHERE ProductId = 23
-- 公用表达式前面的语句必须以分号结束
WITH cte AS
(
SELECT * FROM dbo.T_Product
WHERE ProductId < 10
)
SELECT * FROM cte;
引用对象时带上架构名。
这也是比较推荐的写法。
默认的架构名为dbo 架构是为了便于管理数据库对象(比如表、索引、函数、存储过程、视图)的一个容器。架构可以理解为文件夹、货架。
-- 访问对象用架构名.数据对象名称
SELECT COUNT(1) FROM dbo.T_Product;
-- dbo是默认的架构,访问表时会自动访问dbo架构里的表
SELECT COUNT(1) FROM T_Product;
-- 调用自定义函数(标量值),必须带架构名
SELECT uf_num('100pcs');
SELECT dbo.uf_num('100pcs');
-- 创建物化视图
CREATE VIEW [dbo].[v_test] WITH SCHEMABINDING
AS
-- 访问的对象必须加架构
SELECT productid,code FROM T_Product WHERE ProductId < 100;
--SELECT productid,code FROM dbo.T_Product WHERE ProductId < 100;
推荐安装SQLPrompt第三方工具。
一可以节省编写语句的时间。二可以统一和规范语句编写。以下三种写法,我们认为是完全一样的,但数据库查询优化器认为是不同的。
SELECT COUNT(1) FROM dbo.T_Product WHERE ProductId = 1;
select COUNT(1) from dbo.T_Product WHERE ProductId = 1;
SELECT COUNT(1) FROM dbo.T_Product WHERE productid = 1;