title | date |
---|---|
这些年你需要注意的SQL |
2014/11/14 00:00:00 |
分析: 在SQL SERVER中,如果用户User1访问表table1,那么查询分析器必须决定是检索 User1.table1 还是 dbo.table1 。所以每次User1访问同一张表table1时,查询分析器都必须对查询计划 重编译,影响执行速度。
分析: 采用SELECT * 语法会导致DB对列进行一个遍历,同时可能会查询多余字段数据(本着用啥查啥的原则,建议使用SELECT <Field List>),导致查询性能下降。
分析: 避免造成数据查询异常
分析: 避免表列变化导致插入语句失败
分析: 考虑到并发性,提高查询效率
示例:
SELECT TOP 100 COL1,COL2 FROM TABLE1 t1 WITH (NOLOCK)
分析: 防止结果非预期
示例: (预期结果为2,因为第二次Name2是后添加的。)
CREATE TABLE test6
(
Id int
,Name nvarchar(32)
)
INSERT INTO test6 (Id, Name)
SELECT 1, N'Name1'
UNION all
SELECT 2, N'Name2'
INSERT INTO test6 (Id, Name)
SELECT 3, N'Name2'
--错误的写法
DECLARE @Id int
SELECT
@Id=Id
FROM test6
WHERE
Name = 'Name2'
--正确的写法
DECLARE @Id int
SELECT TOP 1
@Id=Id
FROM test6
WHERE
Name = 'Name2'
分析: 可以用上索引,而且不需要Table Scan
示例:
--错误的写法
SELECT TOP 1 col1 FROM table1 ORDER BY col1 DESC
--正确的写法
SELECT MAX(col1) FROM table1
分析:
- char是固定长度,如果数据不够,会在存储时自动补空格
- varchar是可变长度,会有三个字节来存储字段信息,可以设置最大长度
- nchar和varchar这种以N开头的表示存储unicode编码字符
- 在特定字符集下,如果定义数据格式为char或者是varchar,那么存储特殊字符(包括中文)会乱码
- 关于数据库函数LEN(),是用于返回指定字符串表达式的字符数,其中不包含尾随空格。
- 关于DATALENGTH函数,返回用于表示任何表达式的字节数。
示例:
DECLARE @s1 CHAR(5)
,@s2 VARCHAR(5)
,@s3 NCHAR(5)
,@s4 NVARCHAR(5)
--看看这个结果是什么?
SET @s1 = 'test'
SET @s2 = 'test'
SET @s3 = 'test'
SET @s4 = 'test'
SELECT
LEN(@s1)
,LEN(@s2)
,LEN(@s3)
,Len(@s4)
SELECT
DATALENGTH(@s1)
,DATALENGTH(@s2)
,DATALENGTH(@s3)
,DATALENGTH(@s4)
--如果这样呢?
SET @s1 = '我是中文'
SET @s2 = '我是中文'
SET @s3 = '我是中文'
SET @s4 = '我是中文'
SELECT
LEN(@s1)
,LEN(@s2)
,LEN(@s3)
,Len(@s4)
SELECT
DATALENGTH(@s1)
,DATALENGTH(@s2)
,DATALENGTH(@s3)
,DATALENGTH(@s4)
--一般情况下,SELECT @s1,@s2,@s3,@s4不会显示乱码,是由于安装SQL SERVER的时候后默认字符集是支持unicode字符的。如果遇到不支持的字符集,就需要显示定义字段类型为带N的类型,同时在赋值的时候使用N'中文'这种形式。
分析: 数据库阻塞,你懂的...罪过大大的!
示例:
--思考下结果是什么?
IF NOT exists (SELECT 1)
BEGIN
PRINT 'enter'
DECLARE @table TABLE
(
name nvarchar(32)
)
END
SELECT name FROM @table
分析:
- 在表变量的使用中,会出现如JavaScript一样的定义前置,相当于不管你在哪个条件(也不关心是否能走到这个分支)中定义表变量,那么这个表变量在整个作用域中都是有效的。
- 临时表表现正常
- 表变量和一般的变量有点不一样的地方,表变量也会在tempdb中创建表。示例如下:
CREATE TABLE #TempTable (TT_Col1 INT)
DECLARE @TableVariable TABLE (TV_Col1 INT)
SELECT TOP 2 *
FROM tempdb.sys.tables
ORDER BY create_date DESC
分析:
IF (SELECT COUNT(*) FROM Table WITH (NOLOCK))>0
BEGIN
--Do something
END
--应该用:
IF EXISTS(SELECT TOP 1 1 FROM Table WITH (NOLOCK)
BEGIN
--Do something
END
示例:
SELECT 1
WHERE 't' ='t '
分析:
1.NULL既不能被=匹配,也不能被<>(!=)匹配,只能用IS NULL 或者是 ISNULL()
示例:
CREATE TABLE #tb(col1 int)
INSERT INTO #tb(col1)
SELECT NULL
UNION
SELECT 1
UNION
SELECT 2
SELECT COUNT(*) FROM #tb
WHERE col1 <> 1 OR col1 = 1 --2
SELECT COUNT(*) FROM #tb --3
分析:
- COUNT(0),COUNT(*)计数时会包含NULL值
- COUNT(column)计数时,如果需要该列为NULL,则会忽略计数
示例:
CREATE TABLE #tb(col1 int)
INSERT INTO #tb(col1)
SELECT NULL
UNION
SELECT 1
UNION
SELECT 2
SELECT COUNT(*) FROM #tb --3
SELECT COUNT(0) FROM #tb --3
SELECT COUNT(col1) FROM #tb --2
分析:
- DISTINCT 是数据查询中一个非常慢的操作,所以尽可能的避免
示例:
SELECT DISTINCT
A.au_fname
,A.au_lname
FROM dbo.authors AS A WITH (NOLOCK)
INNER JOIN dbo.titleAuthor AS T WITH (NOLOCK) --一对多的关系
ON T.au_id = A.au_id
--避免DISTINCT的写法
SELECT au_fname
,au_lname
FROM dbo.authors AS A WITH (NOLOCK)
WHERE EXISTS (
SELECT TOP 1 1
FROM dbo.titleAuthor AS T WITH (NOLOCK)
WHERE T.au_id = A.au_id