动态SQL语句基本语法
2011-04-10 13:24
896 查看
1 、普通SQL语句可以用Exec执行 9K p=A
' CdaF r1
eg: Select * from tableName Wsc+A: <"
Exec('select * from tableName') # B tn(
Exec sp_executesql N'select * from tableName' -- 请注意字符串前一定要加N %BfplhE1a
AN &)OIDc
2、字段名,表名,数据库名之类作为变量时,必须用动态SQL H2k3./
Ip
:=r|8#[1]8a
eg: }"|M#
MB
declare @fname varchar(20)
WH$1[Gv7
set @fname = 'FiledName' @#D[C;VvrE
Select @fname from tableName --
错误,不会提示错误,但结果为固定值FiledName,并非所要。
J! _C^,7#
Exec('select ' + @fname + ' from tableName') --
请注意 加号前后的 单引号的边上加空格
\Adve]kD$5
w/r‑;'
\>
当然将字符串改成变量的形式也可
:? Gf%y
declare @fname varchar(20) r~j >XK3
set @fname = 'FiledName' --
设置字段名
[1]!
i9mD!G
w( IfnsP
declare @s varchar(1000) 7A _?mu
set @s = 'select ' + @fname + ' from tableName' ezCY_T9m‑
Exec(@s) --
成功
‑W=Q!_X$
exec sp_executesql @s --
此句会报错
v OwTKUb
By4-}_ T+A
2#sv-v6oH
declare @s Nvarchar(1000) --
注意此处改为
nvarchar(1000) "A^
!?U
OE
set @s = 'select ' + @fname + ' from tableName' (/H[1]v6n3Z&
Exec(@s) --
成功
ix9 Hh{
exec sp_executesql @s --
此句正确
]7UXt*w
LBf0at0
3
、输出参数 "kz/7 E\/A
% +>n<O
declare @num int, - ]n;kS1S
@sqls nvarchar(4000) EI A]sr[1]
set @sqls='select count(*) from tableName' qh C‑5@Do
exec(@sqls) A;vBkAD
--
如何将exec执行结果放入变量中?
f$9`I=j">
~p.M^M`7E
declare @num int, [1]3^={\CUh
@sqls nvarchar(4000) cI)<Js‑w4P
set @sqls='select @a=count(*) from tableName ' 2 c],:zB;%
exec sp_executesql @sqls,N'@a int output',@num output *JA z
^&/
select @num j3SSiM
Ft*Ow%Djzm
此外,如果想要在SQL语句 字符串中使用 单引号 '' 可以 使用 ''''
' CdaF r1
eg: Select * from tableName Wsc+A: <"
Exec('select * from tableName') # B tn(
Exec sp_executesql N'select * from tableName' -- 请注意字符串前一定要加N %BfplhE1a
AN &)OIDc
2、字段名,表名,数据库名之类作为变量时,必须用动态SQL H2k3./
Ip
:=r|8#[1]8a
eg: }"|M#
MB
declare @fname varchar(20)
WH$1[Gv7
set @fname = 'FiledName' @#D[C;VvrE
Select @fname from tableName --
错误,不会提示错误,但结果为固定值FiledName,并非所要。
J! _C^,7#
Exec('select ' + @fname + ' from tableName') --
请注意 加号前后的 单引号的边上加空格
\Adve]kD$5
w/r‑;'
\>
当然将字符串改成变量的形式也可
:? Gf%y
declare @fname varchar(20) r~j >XK3
set @fname = 'FiledName' --
设置字段名
[1]!
i9mD!G
w( IfnsP
declare @s varchar(1000) 7A _?mu
set @s = 'select ' + @fname + ' from tableName' ezCY_T9m‑
Exec(@s) --
成功
‑W=Q!_X$
exec sp_executesql @s --
此句会报错
v OwTKUb
By4-}_ T+A
2#sv-v6oH
declare @s Nvarchar(1000) --
注意此处改为
nvarchar(1000) "A^
!?U
OE
set @s = 'select ' + @fname + ' from tableName' (/H[1]v6n3Z&
Exec(@s) --
成功
ix9 Hh{
exec sp_executesql @s --
此句正确
]7UXt*w
LBf0at0
3
、输出参数 "kz/7 E\/A
% +>n<O
declare @num int, - ]n;kS1S
@sqls nvarchar(4000) EI A]sr[1]
set @sqls='select count(*) from tableName' qh C‑5@Do
exec(@sqls) A;vBkAD
--
如何将exec执行结果放入变量中?
f$9`I=j">
~p.M^M`7E
declare @num int, [1]3^={\CUh
@sqls nvarchar(4000) cI)<Js‑w4P
set @sqls='select @a=count(*) from tableName ' 2 c],:zB;%
exec sp_executesql @sqls,N'@a int output',@num output *JA z
^&/
select @num j3SSiM
Ft*Ow%Djzm
此外,如果想要在SQL语句 字符串中使用 单引号 '' 可以 使用 ''''
SQL Server数据库中经常用到的identity列 |
发布时间:2008.03.24 04:59 来源:赛迪网 作者:Alice |
【赛迪网-IT技术报道】SQL Server中,经常会用到Identity标识列,这种自增长的字段操作起来的确是比较方便。但它有时还会带来一些麻烦。 示例一:当表中被删除了某些数据的时候,自增长列的编号就不再是一个连线的数列。这种时候我们可以用以下方案来解决。
SELECT语句中使用ALL或DISTINCT选项来显示表中符合条件的所有行或删除其中重复的数据行,默认为ALL。使用DISTINCT选项时,对于所有重复的数据行在SELECT返回的结果集合中只保留一行。 5、限制返回的行数 使用TOP n [PERCENT]选项限制返回的数据行数,TOP n说明返回n行,而TOP n PERCENT时,说明n是表示一百分数,指定返回的行数等于总行数的百分之几。
FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图,它们之间用逗号分隔。 在FROM子句同时指定多个表或视图时,如果选择列表中存在同名列,这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应使用下面语句格式加以限定:
表名 as 别名 表名 别名 例如上面语句可用表的别名格式表示为:
(三) 使用WHERE子句设置查询条件 WHERE子句设置查询条件,过滤掉不需要的数据行。例如下面语句查询年龄大于20的数据:
比较运算符(大小比较):> 、> =、=、 <、 <=、 <> 、!> 、! < 范围运算符(表达式值是否在指定的范围):BETWEEN…AND… NOT BETWEEN…AND… 列表运算符(判断表达式是否为列表中的指定项):IN (项1,项2……) NOT IN (项1,项2……) 模式匹配符(判断值是否与指定的字符通配格式相符):LIKE、NOT LIKE 空值判断符(判断表达式是否为空):IS NULL、NOT IS NULL 逻辑运算符(用于多条件的逻辑连接):NOT、AND、OR 1、范围运算符例:age BETWEEN 10 AND 30相当于age> =10 AND age <=30 2、列表运算符例:country IN ( 'Germany ', 'China ') 3、模式匹配符例:常用于模糊查找,它判断列值是否与指定的字符串格式相匹配。可用于char、varchar、text、ntext、datetime和smalldatetime等类型查询。 可使用以下通配字符: 百分号%:可匹配任意类型和长度的字符,如果是中文,请使用两个百分号即%%。 下划线_:匹配单个任意字符,它常用来限制表达式的字符长度。 方括号[]:指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。[^]:其取值也[] 相同,但它要求所匹配对象为指定字符以外的任一个字符。 例如: 限制以Publishing结尾,使用LIKE '%Publishing ' 限制以A开头:LIKE '[A]% ' 限制以A开头外:LIKE '[^A]% ' 4、空值判断符例WHERE age IS NULL 5、逻辑运算符:优先级为NOT、AND、OR (四)查询结果排序 使用ORDER BY子句对查询返回的结果按一列或多列排序。ORDER BY子句的语法格式为:
二、联合查询 UNION运算符可以将两个或两个以上上SELECT语句的查询结果集合合并成一个结果集合显示,即执行联合查询。UNION的语法格式为:
ALL选项表示将所有行合并到结果集合中。不指定该项时,被联合查询结果集合中的重复行将只保留一行。 联合查询时,查询结果的列标题为第一个查询语句的列标题。因此,要定义列标题必须在第一个查询语句中定义。要对联合查询结果排序时,也必须使用第一查询语句中的列名、列标题或者列序号。 在使用UNION 运算符时,应保证每个联合查询语句的选择列表中有相同数量的表达式,并且每个查询选择表达式应具有相同的数据类型,或是可以自动将它们转换为相同的数据类型。在自动转换时,对于数值类型,系统将低精度的数据类型转换为高精度的数据类型。 在包括多个查询的UNION语句中,其执行顺序是自左至右,使用括号可以改变这一执行顺序。例如: 查询1 UNION (查询2 UNION 查询3) 三、连接查询 通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。 在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。为不同实体创建新的表,尔后通过连接进行查询。 连接可以在SELECT 语句的FROM子句或WHERE子句中建立,似是而非在FROM子句中指出连接时有助于将连接操作与WHERE子句中的搜索条件区分开来。所以,在Transact-SQL中推荐使用这种方法。 SQL-92标准所定义的FROM子句的连接语法格式为:
join_type 指出连接类型,可分为三种:内连接、外连接和交叉连接。内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行。根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种。外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接(FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是,外连接不只列出与连接条件相匹配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行。 交叉连接(CROSS JOIN)没有WHERE 子句,它返回连接表中所有数据行的笛卡尔积,其结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。 连接操作中的ON (join_condition) 子句指出连接条件,它由被连接表中的列和比较运算符、逻辑运算符等构成。 无论哪种连接都不能对text、ntext和image数据类型列进行直接连接,但可以对这三种列进行间接连接。例如:
内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值。内连接分三种: 1、等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列。 2、不等连接: 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些运算符包括> 、> =、 <=、 <、!> 、! <和 <> 。 3、自然连接:在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。 例,下面使用等值连接列出authors和publishers表中位于同一城市的作者和出版社:
内连接时,返回查询结果集合中的仅是符合查询条件( WHERE 搜索条件或 HAVING 条件)和连接条件的行。而采用外连接时,它返回到查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。如下面使用左外连接将论坛内容和作者信息连接起来:
交叉连接不带WHERE 子句,它返回被连接的两个表所有数据行的笛卡尔积,返回到结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。例,titles表中有6类图书,而publishers表中有8家出版社,则下列交叉连接检索到的记录数将等。
对第一个SELECT查询使用如下JOIN声明: 以下为引用的内容:
子查询,或叫子选择声明,是在一个查询中将结果组作为资源使用的一个途径。他经常被用来对结果进行限制或定义,而不是运行多个查询或操纵应用软件之中的数据。有了子查询,你可以参考表格来决定数据的内含,或是在一些情况下,返回一个专栏,而这个专栏是一个子选择的结果。 下面的例子中使用了两个表格。一个表格中包含了我想要返回的数据,而另一个表格则给出一个比较点来确定什么数据是我确实感兴趣的。 以下为引用的内容:
5.总结: 缺省情况下建立的索引是非群集索引,但有时它并不是最佳的;合理的索引设计要建立在对各种查询的分析和预测上。 一般来说: ①.有大量重复值、且经常有范围查询(between, >,< ,>=,< =)和order by、group by发生的列,可考虑建立群集索引; ②.经常同时存取多列,且每列都含有重复值可考虑建立组合索引; ③.组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。 二、不充份的连接条件: 例:表card有7896行,在card_no上有一个非聚集索引,表account有191122行,在account_no上有一个非聚集索引,试看在不同的表连接条件下,两个SQL的执行情况:
外层表account上的22541页+(外层表account的191122行*内层表card上对应外层表第一行所要查找的3页)=595907次I/O 在第二个连接条件下,最佳查询方案是将card作外层表,account作内层表,利用account上的索引,其I/O次数可由以下公式估算为:外层表card上的1944页+(外层表card的7896行*内层表account上对应外层表每一行所要查找的4页)= 33528次I/O 可见,只有充份的连接条件,真正的最佳方案才会被执行。 总结: 1.多表操作在被实际执行前,查询优化器会根据连接条件,列出几组可能的连接方案并从中找出系统开销最小的最佳方案。连接条件要充份考虑带有索引的表、行数多的表;内外表的选择可由公式:外层表中的匹配行数*内层表中每一次查找的次数确定,乘积最小为最佳方案。 2.查看执行方案的方法-- 用set showplanon,打开showplan选项,就可以看到连接顺序、使用何种索引的信息;想看更详细的信息,需用sa角色执行dbcc(3604,310,302)。 三、不可优化的where子句 1.例:下列SQL条件语句中的列都建有恰当的索引,但执行速度却非常慢:
where子句中对列的任何操作结果都是在SQL运行时逐列计算得到的,因此它不得不进行表搜索,而没有使用该列上面的索引; 如果这些结果在查询编译时就能得到,那么就可以被SQL优化器优化,使用索引,避免表搜索,因此将SQL重写成下面这样:
2.例:表stuff有200000行,id_no上有非群集索引,请看下面这个SQL: select count(*) from stuff where id_no in('0','1')(23秒) 分析:---- where条件中的'in'在逻辑上相当于'or',所以语法分析器会将in ('0','1')转化为id_no ='0' or id_no='1'来执行。 我们期望它会根据每个or子句分别查找,再将结果相加,这样可以利用id_no上的索引; 但实际上(根据showplan),它却采用了"OR策略",即先取出满足每个or子句的行,存入临时数据库的工作表中,再建立唯一索引以去掉重复行,最后从这个临时表中计算结果。因此,实际过程没有利用id_no上索引,并且完成时间还要受tempdb数据库性能的影响。 实践证明,表的行数越多,工作表的性能就越差,当stuff有620000行时,执行时间竟达到220秒!还不如将or子句分开:
或者,用更好的方法,写一个简单的存储过程:
总结: 大家可以看到,优化即where子句利用了索引,不可优化即发生了表扫描或额外开销。 1.任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。 2.in、or子句常会使用工作表,使索引失效;如果不产生大量重复值,可以考虑把子句拆开;拆开的子句中应该包含索引。 3.要善于使用存储过程,它使SQL变得更加灵活和高效。 从以上这些例子可以看出,SQL优化的实质就是在结果正确的前提下,用优化器可以识别的语句,充份利用索引,减少表扫描的I/O次数,尽量避免表搜索的发生。其实SQL的性能优化是一个复杂的过程,上述这些只是在应用层次的一种体现,深入研究还会涉及数据库层的资源配置、网络层的流量控制以及操作系统层的总体设计。
从别处看到的,本人在用的是DB2,竟然都不一样……看来是不能说“会SQL,所有的数据库用起来都一样”了。 $r2>;Q?Q &f.;ydLYt 1. ORACLE g -HN M[1] SELECT * FROM TABLE1 WHERE ROWNUM<=N m16!oAV?s 2. INFORMIX c tP'\7 9] SELECT FIRST N * FROM TABLE1 > /zA]\^X 3. DB2 4R!W-B 5 SELECT * ROW_NUMBER() OVER(ORDER BY COL1 DESC) AS ROWNUM WHERE ROWNUM<= N bQaDIry'u DB2 lU)6}Q' SELECT COLUMN FROM TABLE FETCH FIRST N ROWS ONLY .+f)f?W‑6 4. SQL SERVER X.LTZfA{ SELECT TOP N * FROM TABLE1 02btp&T4B 5. SYBASE $d,_g ~ SELECT TOP N * FROM TABLE1 7SqsVbLk 6. mysql: Rb(_27T!vW select * from table_name limit N l;&! z ; dLg#,ZGd
UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。如:
推荐方案:采用UNION ALL操作符替代UNION,因为UNION ALL操作只是简单的将两个结果合并后就返回。
同一功能同一性能不同写法SQL的影响 如一个SQL在A程序员写的为
◆WHERE后面的条件顺序影响 WHERE子句后面的条件顺序对大数据量表的查询会产生直接的影响,如
◆查询表顺序的影响 在FROM后面的表中的列表顺序会对SQL执行性能影响,在没有索引及ORACLE没有对表进行统计分析的情况下ORACLE会按表出现的顺序进行链接,由此因为表的顺序不对会产生十分耗服务器资源的数据交叉。(注:如果对表进行了统计分析,ORACLE会自动先进小表的链接,再进行大表的链接) ◆SQL语句索引的利用 对操作符的优化(见上节) 对条件字段的一些优化 ◆采用函数处理的字段不能利用索引,如:
条件内包括了多个本表的字段运算时不能进行索引,如:
提示处理是在ORACLE产生的SQL分析执行路径不满意的情况下要用到的。它可以对SQL进行以下方面的提示 ◆目标方面的提示:
INDEX(TABLE INDEX)(使用提示的表索引进行查询) 其它高级提示(如并行处理等等)
问题所在: 虽然在性能上,两者没有什么差异,但另一个问题也许你从来没有考虑过,那就是对表的访问的问题,在方法A中,肯定只会访问到一个表;而在方法B中,情况还是如此吗?答案是否定的,方法B始终会扫描两个表。而这样的潜台词是,即使在我的查询中,只会用到A表,但如果B表被下了锁的话,整个查询就会被阻塞,而方法A不会。 为了证明这个问题,我们再做下面的测试 BLOCK 的测试—为表A加锁: (查询窗口A)
可以看到,查询窗口B中的查询会及时地完成,而查询窗口C的查询会一直等待,你可以通过执行存储过程 sp_who2,查看当前的BLOCK状况来确定查询窗口C的查询是否被查询窗口A的查询BLOCK住。 最后结论: 不要使用查询方法B,它看起来很不错,实际的结果即则是会增加被BLOCK的机会。
经过几分钟的测试运行后,我们可以发现SQL124的运行时间和反应时间最短。运行速度约有22.75倍的提升(源SQL语句运行时间为2.73秒,SQL124运行时间为0.12秒)。现在我们就可以把SQL124放入源代码中,结束一条SQL语句的优化工作了。 “边做边学式训练”提升SQL开发水平 LECCO SQL Expert不仅能够找到最佳的SQL语句,它所提供的“边做边学式训练”还能够教开发人员和数据库管理员如何写出性能最好的SQL语句。LECCO SQL Expert的“SQL比较器”可以标明源SQL和待选SQL间的不同之处。 以上面优化的结果为例,为了查看源SQL语句和SQL124在写法上有什么不同,我们可以按下“比较器” 按钮,对SQL124和源SQL语句进行比较。“SQL 比较器”将SQL124相对于源SQL语句的不同之处以蓝颜色表示了出来。如果选择“双向比较”复选框,“SQL 比较器”可以将两条SQL语句的不同之处以蓝色表示。当然,我们也可以从源语句和重写后的SQL 语句中任选两条进行比较。 从比较的结果可以看到,重写后的SQL124把第一个Exists改写成了In;在字段DPT_ID上进行了合并空字符串的操作,以诱导数据库先执行子查询中的 (SELECT DPT_ID||'' FROM DEPARTMENT WHERE DPT_NAME LIKE 'AC%') 在子查询完成后,再与EMPLOYEE表进行嵌套循环连接(Nested Loop Join)。 如果觉得对写法的改变难以理解,还可以点中“执行计划”复选框,通过比较两条SQL语句的执行计划的不同,来了解其中的差异。在查看执行计划过程中,如果有什么不明白的地方,可以点中“SQL信息按钮”,再点击执行计划看不明白的地方,LECCO SQL Expert的上下文敏感帮助系统将提供执行计划该处的解释。 在“SQL比较器”中,选中“统计信息”复选框后,可得到详细的两条SQL语句运行时的统计信息比较,这对于学习不同的SQL写法对数据库资源的消耗很有帮助。 LECCO SQL Expert优化模块的特点 LECCO SQL Expert优化模块的特点主要表现为:自动优化SQL语句;以独家的人工智能知识库“反馈式搜索引擎”来重写性能优异的SQL语句;找出所有等效的SQL语句及可能的执行计划;保证产生相同的结果;先进的SQL语法分析器能处理最复杂的SQL语句;可以重写SELECT、SELECT INTO、UPDATE、INSERT和DELETE语句;通过测试运行,为应用程序和数据库自动找到性能最好的SQL语句;提供微秒级的计时,能够优化Web应用程序和有大量用户的在线事务处理中运行时间很短的SQL语句;为开发人员提供“边做边学式训练”,迅速提高开发人员的SQL编程技能;提供上下文敏感的执行计划帮助系统和SQL运行状态帮助;不是猜测或建议,而是独一无二的SQL重写解决方案。 写出专家级的SQL语句 LECCO SQL Expert的出现,使SQL的优化变得极其简单,只要能够写出SQL语句,它就能帮用户找到最好性能的写法。LECCO SQL Expert不仅能在很短的时间内找到所有可能的优化方案,而且能够通过实际测试,确定最有效的优化方案。同以往的数据库优化手段相比较,LECCO SQL Expert将数据库优化技术带到了一个崭新的技术高度,依赖人的经验、耗费大量时间、受人的思维束缚的数据库优化手段已经被高效、省时且准确的自动优化软件所取代了。通过内建的“LECCO小助手”的帮助,即使是SQL的开发新手,也能快速且简单地写出专家级的SQL语句。 相关文章推荐
|