﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-永远不提放弃！-文章分类-数据库开发</title><link>http://www.cnitblog.com/malan11/category/5849.html</link><description>很多事情，在关键时刻总会峰回路转！</description><language>zh-cn</language><lastBuildDate>Mon, 03 Oct 2011 03:49:09 GMT</lastBuildDate><pubDate>Mon, 03 Oct 2011 03:49:09 GMT</pubDate><ttl>60</ttl><item><title>SQL循环语句</title><link>http://www.cnitblog.com/malan11/articles/31153.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 06:57:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31153.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31153.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31153.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31153.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31153.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; declare @i int<br>set @i=1<br>while @i&lt;30<br>begin<br>insert into test (userid) values(@i)<br>set @i=@i+1<br>end </p>
<p>---------------</p>
<p>while 条件<br>begin<br>执行操作<br>set @i=@i+1<br>end </p>
<p>WHILE<br>设置重复执行 SQL 语句或语句块的条件。只要指定的条件为真，就重复执行语句。可以使用 BREAK 和 CONTINUE 关键字在循环内部控制 WHILE 循环中语句的执行。</p>
<p>语法<br>WHILE Boolean_expression<br>&nbsp;&nbsp;&nbsp;&nbsp; { sql_statement | statement_block }<br>&nbsp;&nbsp;&nbsp;&nbsp; [ BREAK ]<br>&nbsp;&nbsp;&nbsp;&nbsp; { sql_statement | statement_block }<br>&nbsp;&nbsp;&nbsp;&nbsp; [ CONTINUE ]</p>
<p>参数<br>Boolean_expression</p>
<p>返回 TRUE 或 FALSE 的表达式。如果布尔表达式中含有 SELECT 语句，必须用圆括号将 SELECT 语句括起来。</p>
<p>{sql_statement | statement_block}</p>
<p>Transact-SQL 语句或用语句块定义的语句分组。若要定义语句块，请使用控制流关键字 BEGIN 和 END。 </p>
<p>BREAK</p>
<p>导致从最内层的 WHILE 循环中退出。将执行出现在 END 关键字后面的任何语句，END 关键字为循环结束标记。 </p>
<p>CONTINUE</p>
<p>使 WHILE 循环重新开始执行，忽略 CONTINUE 关键字后的任何语句。</p>
<p>注释<br>如果嵌套了两个或多个 WHILE 循环，内层的 BREAK 将导致退出到下一个外层循环。首先运行内层循环结束之后的所有语句，然后下一个外层循环重新开始执行。</p>
<p>示例<br>A. 在嵌套的 IF...ELSE 和 WHILE 中使用 BREAK 和 CONTINUE<br>在下例中，如果平均价格少于 $30，WHILE 循环就将价格加倍，然后选择最高价。如果最高价少于或等于 $50，WHILE 循环重新启动并再次将价格加倍。该循环不断地将价格加倍直到最高价格超过 $50，然后退出 WHILE 循环并打印一条消息。</p>
<p>USE pubs<br>GO<br>WHILE (SELECT AVG(price) FROM titles) &lt; $30<br>BEGIN<br>&nbsp;&nbsp;&nbsp; UPDATE titles<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET price = price * 2<br>&nbsp;&nbsp;&nbsp; SELECT MAX(price) FROM titles<br>&nbsp;&nbsp;&nbsp; IF (SELECT MAX(price) FROM titles) &gt; $50<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BREAK<br>&nbsp;&nbsp;&nbsp; ELSE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CONTINUE<br>END<br>PRINT 'Too much for the market to bear'</p>
<p>B. 在带有游标的过程中使用 WHILE<br>以下的 WHILE 结构是名为 count_all_rows 过程中的一部分。下例中，该 WHILE 结构测试用于游标的函数 @@FETCH_STATUS 的返回值。因为 @@FETCH_STATUS 可能返回 &#8211;2、-1 或 0，所以，所有的情况都应进行测试。如果某一行在开始执行此存储过程以后从游标结果中删除，将跳过该行。成功提取 (0) 后将执行 BEGIN...END 循环内部的 SELECT 语句。</p>
<p>USE pubs<br>DECLARE tnames_cursor CURSOR<br>FOR<br>&nbsp;&nbsp;&nbsp; SELECT TABLE_NAME <br>&nbsp;&nbsp;&nbsp; FROM INFORMATION_SCHEMA.TABLES<br>OPEN tnames_cursor<br>DECLARE @tablename sysname<br>--SET @tablename = 'authors'<br>FETCH NEXT FROM tnames_cursor INTO @tablename<br>WHILE (@@FETCH_STATUS &lt;&gt; -1)<br>BEGIN<br>&nbsp;&nbsp;&nbsp; IF (@@FETCH_STATUS &lt;&gt; -2)<br>&nbsp;&nbsp;&nbsp; BEGIN&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT @tablename = RTRIM(@tablename) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EXEC ('SELECT ''' + @tablename + ''' = count(*) FROM ' <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + @tablename )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT ' '<br>&nbsp;&nbsp; END<br>&nbsp;&nbsp;&nbsp; FETCH NEXT FROM tnames_cursor INTO @tablename<br>END<br>CLOSE tnames_cursor<br>DEALLOCATE tnames_cursor<br></p>
<img src ="http://www.cnitblog.com/malan11/aggbug/31153.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 14:57 <a href="http://www.cnitblog.com/malan11/articles/31153.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL记录自增处理</title><link>http://www.cnitblog.com/malan11/articles/31151.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 06:51:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31151.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31151.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31151.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31151.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31151.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 写存储过程的时候，经常碰到要做序号处理。。。。有时候不好处理，这里，留下常见的处理方法。。。<br>方法1：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; create table #temp<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (ID&nbsp; &nbsp;int identity(1,1),其他字段............)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样可以在临时表插入数据的时候自动做序号自增处理<br>方法2：<br>&nbsp;&nbsp;&nbsp;&nbsp; select identity(int,1,1) as id , * into #temp from 原表<br>&nbsp;&nbsp;&nbsp;&nbsp; 直接做插表处理。自动插入序号<br><br>对ID重置的方法有：&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;方法１：<br>truncate table 你的表名 这样不但将数据删除，而且可以重新置位identity属性的字段。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 方法２：<br>delete from 你的表名<br>dbcc checkident(你的表名,reseed,0) --重新置位identity属性的字段，让其下个从值1开始。</p>
<img src ="http://www.cnitblog.com/malan11/aggbug/31151.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 14:51 <a href="http://www.cnitblog.com/malan11/articles/31151.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL语句集锦</title><link>http://www.cnitblog.com/malan11/articles/31146.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 05:50:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31146.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31146.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31146.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31146.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31146.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 12pt">--语 句 功 能<br>--数据操作<br>SELECT --从数据库表中检索数据行和列<br>INSERT --向数据库表添加新数据行<br>DELETE --从数据库表中删除数据行<br>UPDATE --更新数据库表中的数据<br>--数据定义<br>CREATE TABLE --创建一个数据库表<br>DROP TABLE --从数据库中删除表<br>ALTER TABLE --修改数据库表结构<br>CREATE VIEW --创建一个视图<br>DROP VIEW --从数据库中删除视图<br>CREATE INDEX --为数据库表创建一个索引<br>DROP INDEX --从数据库中删除索引<br>CREATE PROCEDURE --创建一个存储过程 <br>DROP PROCEDURE --从数据库中删除存储过程<br>CREATE TRIGGER --创建一个触发器<br>DROP TRIGGER --从数据库中删除触发器<br>CREATE SCHEMA --向数据库添加一个新模式<br>DROP SCHEMA --从数据库中删除一个模式<br>CREATE DOMAIN --创建一个数据值域<br>ALTER DOMAIN --改变域定义<br>DROP DOMAIN --从数据库中删除一个域<br>--数据控制<br>GRANT --授予用户访问权限<br>DENY --拒绝用户访问<br>REVOKE --解除用户访问权限<br>--事务控制<br>COMMIT --结束当前事务<br>ROLLBACK --中止当前事务<br>SET TRANSACTION --定义当前事务数据访问特征<br>--程序化SQL<br>DECLARE --为查询设定游标<br>EXPLAN --为查询描述数据访问计划<br>OPEN --检索查询结果打开一个游标<br>FETCH --检索一行查询结果<br>CLOSE --关闭游标<br>PREPARE --为动态执行准备SQL 语句<br>EXECUTE --动态地执行SQL 语句<br>DESCRIBE --描述准备好的查询<br>---局部变量<br>declare @id char(10)<br>--set @id = '10010001'<br>select @id = '10010001'<br>---全局变量<br>---必须以@@开头<br>--IF ELSE<br>declare @x int @y int @z int<br>select @x = 1 @y = 2 @z=3<br>if @x &gt; @y<br>print 'x &gt; y' --打印字符串'x &gt; y'<br>else if @y &gt; @z<br>print 'y &gt; z'<br>else print 'z &gt; y'<br>--CASE<br>use pangu<br>update employee<br>set e_wage =<br>case<br>when job_level = '1' then e_wage*1.08<br>when job_level = '2' then e_wage*1.07<br>when job_level = '3' then e_wage*1.06<br>else e_wage*1.05<br>end<br>--WHILE CONTINUE BREAK<br>declare @x int @y int @c int<br>select @x = 1 @y=1<br>while @x &lt; 3<br>begin<br>print @x --打印变量x 的值<br>while @y &lt; 3<br>begin<br>select @c = 100*@x + @y<br>print @c --打印变量c 的值<br>select @y = @y + 1<br>end<br>select @x = @x + 1<br>select @y = 1<br>end<br>--WAITFOR<br>--例 等待1 小时2 分零3 秒后才执行SELECT 语句<br>waitfor delay '01:02:03'<br>select * from employee<br>--例 等到晚上11 点零8 分后才执行SELECT 语句<br>waitfor time '23:08:00'<br>select * from employee<br><br>***SELECT***<br>select *(列名) from table_name(表名) where column_name operator value<br>ex:(宿主)<br>select * from stock_information where stockid = str(nid)<br>stockname = 'str_name' <br>stockname like '% find this %' <br>stockname like '[a-zA-Z]%' --------- ([]指定值的范围)<br>stockname like '[^F-M]%' --------- (^排除指定范围)<br>--------- 只能在使用like关键字的where子句中使用通配符)<br>or stockpath = 'stock_path'<br>or stocknumber &lt; 1000<br>and stockindex = 24<br>not stocksex = 'man'<br>stocknumber between 20 and 100<br>stocknumber in(10,20,30)<br>order by stockid desc(asc) --------- 排序，desc-降序，asc-升序<br>order by 1,2 --------- by列号<br>stockname = (select stockname from stock_information where stockid = 4)<br>--------- 子查询<br>--------- 除非能确保内层select只返回一个行的值，<br>--------- 否则应在外层where子句中用一个in限定符<br>select distinct column_name form table_name --------- distinct指定检索独有的列值，不重复<br>select stocknumber ,"stocknumber + 10" = stocknumber + 10 from table_name<br>select stockname , "stocknumber" = count(*) from table_name group by stockname<br>--------- group by 将表按行分组,指定列中有相同的值<br>having count(*) = 2 --------- having选定指定的组<br><br>select * <br>from table1, table2 <br>where table1.id *= table2.id -------- 左外部连接，table1中有的而table2中没有得以null表示<br>table1.id =* table2.id -------- 右外部连接 <br>select stockname from table1<br>union [all] ----- union合并查询结果集，all-保留重复行<br>select stockname from table2<br>***insert***<br>insert into table_name (Stock_name,Stock_number) value ("xxx","xxxx")<br>value (select Stockname , Stocknumber from Stock_table2)---value为select语句<br>***update***<br>update table_name set Stockname = "xxx" [where Stockid = 3]<br>Stockname = default<br>Stockname = null<br>Stocknumber = Stockname + 4<br>***delete***<br>delete from table_name where Stockid = 3<br>truncate table_name ----------- 删除表中所有行，仍保持表的完整性<br>drop table table_name --------------- 完全删除表<br>***alter table*** --- 修改数据库表结构<br>alter table database.owner.table_name add column_name char(2) null .....<br>sp_help table_name ---- 显示表已有特征<br>create table table_name (name char(20), age smallint, lname varchar(30))<br>insert into table_name select ......... ----- 实现删除列的方法（创建新表）<br>alter table table_name drop constraint Stockname_default ---- 删除Stockname的default约束<br><br>***function(/*常用函数*/)***<br>----统计函数----<br>AVG --求平均值<br>COUNT --统计数目<br>MAX --求最大值<br>MIN --求最小值<br>SUM --求和<br>--AVG<br>use pangu<br>select avg(e_wage) as dept_avgWage<br>from employee<br>group by dept_id<br>--MAX<br>--求工资最高的员工姓名<br>use pangu<br>select e_name<br>from employee<br>where e_wage =<br>(select max(e_wage)<br>from employee)<br>--STDEV()<br>--STDEV()函数返回表达式中所有数据的标准差<br>--STDEVP()<br>--STDEVP()函数返回总体标准差<br>--VAR()<br>--VAR()函数返回表达式中所有值的统计变异数<br>--VARP()<br>--VARP()函数返回总体变异数<br>----算术函数----<br>/***三角函数***/<br>SIN(float_expression) --返回以弧度表示的角的正弦<br>COS(float_expression) --返回以弧度表示的角的余弦<br>TAN(float_expression) --返回以弧度表示的角的正切<br>COT(float_expression) --返回以弧度表示的角的余切<br>/***反三角函数***/<br>ASIN(float_expression) --返回正弦是FLOAT 值的以弧度表示的角<br>ACOS(float_expression) --返回余弦是FLOAT 值的以弧度表示的角<br>ATAN(float_expression) --返回正切是FLOAT 值的以弧度表示的角<br>ATAN2(float_expression1,float_expression2) <br>--返回正切是float_expression1 /float_expres-sion2的以弧度表示的角<br>DEGREES(numeric_expression)<br>--把弧度转换为角度返回与表达式相同的数据类型可为<br>--INTEGER/MONEY/REAL/FLOAT 类型<br>RADIANS(numeric_expression) --把角度转换为弧度返回与表达式相同的数据类型可为<br>--INTEGER/MONEY/REAL/FLOAT 类型<br>EXP(float_expression) --返回表达式的指数值<br>LOG(float_expression) --返回表达式的自然对数值<br>LOG10(float_expression)--返回表达式的以10 为底的对数值<br>SQRT(float_expression) --返回表达式的平方根<br>/***取近似值函数***/<br>CEILING(numeric_expression) --返回&gt;=表达式的最小整数返回的数据类型与表达式相同可为<br>--INTEGER/MONEY/REAL/FLOAT 类型<br>FLOOR(numeric_expression) --返回&lt;=表达式的最小整数返回的数据类型与表达式相同可为 <br>--INTEGER/MONEY/REAL/FLOAT 类型<br>ROUND(numeric_expression) --返回以integer_expression 为精度的四舍五入值返回的数据<br>--类型与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型<br>ABS(numeric_expression) --返回表达式的绝对值返回的数据类型与表达式相同可为<br>--INTEGER/MONEY/REAL/FLOAT 类型<br>SIGN(numeric_expression) --测试参数的正负号返回0 零值1 正数或-1 负数返回的数据类型<br>--与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型<br>PI() --返回值为&#960; 即3.1415926535897936<br>RAND([integer_expression]) --用任选的[integer_expression]做种子值得出0-1 间的随机浮点数</p>
<p style="FONT-SIZE: 12pt">----字符串函数----<br>ASCII() --函数返回字符表达式最左端字符的ASCII 码值<br>CHAR() --函数用于将ASCII 码转换为字符<br>--如果没有输入0 ~ 255 之间的ASCII 码值CHAR 函数会返回一个NULL 值<br>LOWER() --函数把字符串全部转换为小写<br>UPPER() --函数把字符串全部转换为大写<br>STR() --函数把数值型数据转换为字符型数据<br>LTRIM() --函数把字符串头部的空格去掉<br>RTRIM() --函数把字符串尾部的空格去掉<br>LEFT(),RIGHT(),SUBSTRING() --函数返回部分字符串<br>CHARINDEX(),PATINDEX() --函数返回字符串中某个指定的子串出现的开始位置<br>SOUNDEX() --函数返回一个四位字符码 <br>--SOUNDEX函数可用来查找声音相似的字符串但SOUNDEX函数对数字和汉字均只返回0 值 <br>DIFFERENCE() --函数返回由SOUNDEX 函数返回的两个字符表达式的值的差异<br>--0 两个SOUNDEX 函数返回值的第一个字符不同<br>--1 两个SOUNDEX 函数返回值的第一个字符相同<br>--2 两个SOUNDEX 函数返回值的第一二个字符相同<br>--3 两个SOUNDEX 函数返回值的第一二三个字符相同<br>--4 两个SOUNDEX 函数返回值完全相同<br><br>QUOTENAME() --函数返回被特定字符括起来的字符串<br>/*select quotename('abc', '{') quotename('abc')<br>运行结果如下<br>----------------------------------{<br>{abc} [abc]*/<br>REPLICATE() --函数返回一个重复character_expression 指定次数的字符串<br>/*select replicate('abc', 3) replicate( 'abc', -2)<br>运行结果如下<br>----------- -----------<br>abcabcabc NULL*/<br>REVERSE() --函数将指定的字符串的字符排列顺序颠倒<br>REPLACE() --函数返回被替换了指定子串的字符串<br>/*select replace('abc<st1:chmetcnv w:st="on" UnitName="g" SourceValue="123" HasSpace="False" Negative="False" NumberType="1" TCSC="0">123g</st1:chmetcnv>', '123', 'def')<br>运行结果如下<br>----------- -----------<br>abcdefg*/<br>SPACE() --函数返回一个有指定长度的空白字符串<br>STUFF() --函数用另一子串替换字符串指定位置长度的子串</p>
<p style="FONT-SIZE: 12pt">----数据类型转换函数----<br>CAST() 函数语法如下<br>CAST() (&lt;expression&gt; AS &lt;data_ type&gt;[ length ])<br>CONVERT() 函数语法如下<br>CONVERT() (&lt;data_ type&gt;[ length ], &lt;expression&gt; [, style])<br>select cast(100+99 as char) convert(varchar(12), getdate())<br>运行结果如下<br>------------------------------ ------------<br>199 Jan 15 2000<br>----日期函数----<br>DAY() --函数返回date_expression 中的日期值<br>MONTH() --函数返回date_expression 中的月份值<br>YEAR() --函数返回date_expression 中的年份值<br>DATEADD(&lt;datepart&gt; ,&lt;number&gt; ,&lt;date&gt;) <br>--函数返回指定日期date 加上指定的额外日期间隔number 产生的新日期<br>DATEDIFF(&lt;datepart&gt; ,&lt;number&gt; ,&lt;date&gt;)<br>--函数返回两个指定日期在datepart 方面的不同之处<br>DATENAME(&lt;datepart&gt; , &lt;date&gt;) --函数以字符串的形式返回日期的指定部分<br>DATEPART(&lt;datepart&gt; , &lt;date&gt;) --函数以整数值的形式返回日期的指定部分<br>GETDATE() --函数以DATETIME 的缺省格式返回系统当前的日期和时间<br>----系统函数----<br>APP_NAME() --函数返回当前执行的应用程序的名称<br>COALESCE() --函数返回众多表达式中第一个非NULL 表达式的值<br>COL_LENGTH(&lt;'table_name'&gt;, &lt;'column_name'&gt;) --函数返回表中指定字段的长度值<br>COL_NAME(&lt;table_id&gt;, &lt;column_id&gt;) --函数返回表中指定字段的名称即列名<br>DATALENGTH() --函数返回数据表达式的数据的实际长度<br>DB_ID(['database_name']) --函数返回数据库的编号<br>DB_NAME(database_id) --函数返回数据库的名称<br>HOST_ID() --函数返回服务器端计算机的名称<br>HOST_NAME() --函数返回服务器端计算机的名称<br>IDENTITY(&lt;data_type&gt;[, seed increment]) [AS column_name])<br>--IDENTITY() 函数只在SELECT INTO 语句中使用用于插入一个identity column列到新表中<br>/*select identity(int, 1, 1) as column_name<br>into newtable<br>from oldtable*/<br>ISDATE() --函数判断所给定的表达式是否为合理日期<br>ISNULL(&lt;check_expression&gt;, &lt;replacement_value&gt;) --函数将表达式中的NULL 值用指定值替换<br>ISNUMERIC() --函数判断所给定的表达式是否为合理的数值<br>NEWID() --函数返回一个UNIQUEIDENTIFIER 类型的数值<br>NULLIF(&lt;expression1&gt;, &lt;expression2&gt;)<br>--NULLIF 函数在expression1 与expression2 相等时返回NULL 值若不相等时则返回expression1 的值</p>
<img src ="http://www.cnitblog.com/malan11/aggbug/31146.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 13:50 <a href="http://www.cnitblog.com/malan11/articles/31146.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>临时表操作的一些见解</title><link>http://www.cnitblog.com/malan11/articles/31145.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 05:43:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31145.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31145.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31145.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31145.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31145.html</trackback:ping><description><![CDATA[<span>在调试以下存储过程中遇到了很大的困扰（主要是临时表操作）：</span><span><br>CREATE PROCEDURE [c_readtop] @eachrow int=10 AS<br>declare @tmpcat varchar(16)<br>create table #tmp_result (arid int,cat2 varchar(16),title varchar(100),upday datetime)<br>declare rt_cursor cursor<br>for select cat2 from category where cat1='</span><span>电脑手册</span><span>' and catl=2<br>open rt_cursor<br>fetch from rt_cursor into @tmpcat<br>while @@fetch_status=0<br>&nbsp;&nbsp;Begin<br>&nbsp;&nbsp;&nbsp;set rowcount @eachrow<br>&nbsp;&nbsp;&nbsp;Insert into #tmp_result (arid,cat2,title,upday) Select top 10 arid,cat2,title,upday from article as a <br>left join category as b on a.sortid=b.catid where b.cat1='</span><span>电脑手册</span><span>' and b.cat2=@tmpcat order by upday desc<br>&nbsp;&nbsp;&nbsp;fetch from rt_cursor into @tmpcat<br>&nbsp;&nbsp;End<br>select * from #tmp_result<br>drop table #tmp_result<br>close rt_cursor<br>deallocate rt_cursor<br><br></span><span>此存储过程的作用是取出每个分类的最新</span><span>10</span><span>条记录。</span><span><br></span><span>出现的错误信息是（一旦操作返回的记录集时就出现）：</span><span><br>ADODB.Recordset </span><span>错误</span><span> '<st1:chmetcnv w:st="on" UnitName="a" SourceValue="800" HasSpace="False" Negative="False" NumberType="1" TCSC="0">800a</st1:chmetcnv>0e78' <br><br>The operation requested by the application is not allowed if the object is closed. <br></span><span>此存储过程能在</span><span>qa</span><span>中正常运行且能得到正确结果，使用</span><span>odbc</span><span>连接数据库的话，也能得到正确的结果。于是首先怀疑</span><span>oledb</span><span>方</span><span><br></span><span>式连接没能返回记录集。进行了下面的调试：</span><span><br></span><span>（一）加调试标记，在调用记录集前用</span><span>set rs=rs.nextrecordset</span><span>测试是不是命中返回的记录集</span><span>&#8230;&#8230;<br></span><span>（二）由于该过存原来是另一个过程的一部分，怀疑存储过程中有些语句不能同时使用，于是将该过程分离成一个独立的</span><span><br></span><span>存储过程，错误依旧。</span><span><br></span><span>（三）怀疑调用该过程的</span><span>Asp</span><span>有问题，于是重做一个只是调用该存储过程的</span><span>Asp</span><span>程序，错误依旧。</span><span><br></span><span>（四）将连接方式改为</span><span>odbc</span><span>方式连接（建</span><span>dsn</span><span>，设</span><span>sql server</span><span>的</span><span>login ID</span><span>，设权限），该错误消失。重新使用</span><span>oledb</span><span>连接，</span><span><br></span><span>错误依旧。</span><span><br></span><span>（五）怀疑对临时表的数据插入有问题，取消去临时表插入数据，能返回一个空的记录集。</span><span><br></span><span>（六）经</span><span>Bigeagle</span><span>提示，将临时表建在临时数据库</span><span>tempdb</span><span>上，错误依旧</span><span><br></span><span>（七）把存储过程中的</span><span>drop table</span><span>去掉，在</span><span>qa</span><span>中运行该存储过程，观察临时表的生成情况，发现临时表正确生成且有正确</span><span><br></span><span>的数据插入，百思不得其解，数据输出到哪了？</span><span><br></span><span>（八）经</span><span>Bigeagle</span><span>提示</span><span>create table</span><span>一句返回了记录集，于是重新在输出记录集前使用多个</span><span>set rs=rs.nextrecordset</span><span>（最</span><span><br></span><span>多放上了</span><span>4</span><span>个），错误提示依旧。</span><span><br></span><span>（九）怀疑临时表操作有问题，将临时表改为固定表，不插入数据时返回空记录集，插入记录时仍然提示错误。在记录集</span><span><br></span><span>输出前先执行一个或多个</span><span>set rs=rs.nextrecordset</span><span>，终于有一次没有提示出错（检测到</span><span>rs.eof</span><span>为</span><span>false</span><span>），于是才恍然大</span><span><br></span><span>悟</span><span>——</span><span>不但是</span><span>create table</span><span>返回了记录集，而且连</span><span>insert into</span><span>语句也返回了记录集，不过该记录集得一种特别的记录集</span><span><br></span><span>（没有字段，不能对该记录集进行任何操作</span><span>——</span><span>连检测</span><span>rs.eof</span><span>都不允许），我在此将它称为特殊的记录集，方便下面引</span><span><br></span><span>用。</span><span><br></span><span>（十）知道了问题的症结，就马上解决了，在存储过程中不希望返回记录集前执行</span><span>set nocount on</span><span>，要返回记录集时，先</span><span><br></span><span>执行</span><span>set nocount off</span><span>。</span><span><br><br></span><span>也就是改成：</span><span><br>CREATE PROCEDURE [c_readtop] @eachrow int=10 AS<br>declare @tmpcat varchar(16)<br>set nocount on<br>create table #tmp_result (arid int,cat2 varchar(16),title varchar(100),upday datetime)<br>declare rt_cursor cursor<br>for select cat2 from category where cat1='</span><span>电脑手册</span><span>' and catl=2<br>open rt_cursor<br>fetch from rt_cursor into @tmpcat<br>while @@fetch_status=0<br>&nbsp;&nbsp;Begin<br>&nbsp;&nbsp;&nbsp;set rowcount @eachrow<br>&nbsp;&nbsp;&nbsp;Insert into #tmp_result (arid,cat2,title,upday) Select top 10 arid,cat2,title,upday from article as a <br>left join category as b on a.sortid=b.catid where b.cat1='</span><span>电脑手册</span><span>' and b.cat2=@tmpcat order by upday desc<br>&nbsp;&nbsp;&nbsp;fetch from rt_cursor into @tmpcat<br>&nbsp;&nbsp;End<br>set nocount off<br>select * from #tmp_result<br>drop table #tmp_result<br>close rt_cursor<br>deallocate rt_cursor<br></span><span>问题解决。</span><span><br><span>&nbsp;&nbsp; </span>&nbsp;</span><span>在该存储过程调试过程中，发现</span><span>oledb</span><span>和</span><span>odbc</span><span>存在一个很大的差别，</span><span>asp</span><span>向</span><span>odbc</span><span>取记录集时，</span><span>odbc</span><span>过滤了上面所称的特</span><span><br></span><span>殊记录集（那种只占位置但不能进行任何操作的记录集</span><span>——</span><span>多由</span><span>create table</span><span>或</span><span>insert into</span><span>产生），而</span><span>asp</span><span>向</span><span>oledb</span><span>取记录</span><span><br></span><span>集时，</span><span>oledb</span><span>并没有将特殊记录集过滤。</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>同时，认识到在使用存储过程返回记录集时，在不希望返回记录的地方，应该使用</span><span>set nocount on</span><span>禁止存储过程返回</span><span><br></span><span>记录集，否则可能会绕很多弯路。</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>终于明白了为什么绕了这么多弯路：没有想到</span><span>oledb</span><span>返回了这么多特殊的记录集（还是由一个循环产生的，该循环执行</span><span><br></span><span>次数</span><span>5</span><span>、</span><span>6</span><span>次），怪不得在取记录集前虽然执行了</span><span>set rs=rs.nextrecordset</span><span>，但终因数据不够多而未能发现错误症结所在。</span><span><br><br></span>
<img src ="http://www.cnitblog.com/malan11/aggbug/31145.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 13:43 <a href="http://www.cnitblog.com/malan11/articles/31145.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL Server 数据库管理常用的SQL和T-SQL语句</title><link>http://www.cnitblog.com/malan11/articles/31144.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 05:39:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31144.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31144.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31144.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31144.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31144.html</trackback:ping><description><![CDATA[<span><span>&nbsp;
<p><span><span>1. </span></span><span><span>查看数据库的版本</span></span><span><br><span>select @@version</span></span><span></span></p>
<p><span><span>2. </span></span><span><span>查看数据库所在机器操作系统参数</span></span><span><br><span>exec master..xp_msver</span> <br><span>3. </span></span><span><span>查看数据库启动的参数</span></span><span><br><span>sp_configure</span> <br><span>4. </span></span><span><span>查看数据库启动时间</span></span><span><br><span>select convert(varchar(30),login_time,120) from master..sysprocesses where spid=1</span></span><span></span></p>
<p><span><span>查看数据库服务器名和实例名</span></span><span><br><span>print ''Server Name...............: '' + convert(varchar(30),@@SERVERNAME)</span> <br><span>print ''Instance..................: '' + convert(varchar(30),@@SERVICENAME)</span> <br><span>5. </span></span><span><span>查看所有数据库名称及大小</span></span><span><br><span>sp_helpdb</span></span><span></span></p>
<p><span><span>重命名数据库用的</span></span><span><span>SQL</span></span><span> <br><span>sp_renamedb ''old_dbname'', ''new_dbname''</span><br><span>6. </span></span><span><span>查看所有数据库用户登录信息</span></span><span><br><span>sp_helplogins</span></span><span></span></p>
<p><span><span>查看所有数据库用户所属的角色信息</span></span><span><br><span>sp_helpsrvrolemember</span></span><span></span></p>
<p><span><span>修复迁移服务器时孤立用户时</span></span><span><span>,</span></span><span><span>可以用的</span></span><span><span>fix_orphan_user</span></span><span><span>脚本或者</span></span><span><span>LoneUser</span></span><span><span>过程</span></span><span></span></p>
<p><span><span>更改某个数据对象的用户属主</span></span><span><br><span>sp_changeobjectowner [@objectname =] ''object'', [@newowner =] ''owner''</span> <br></span><span><span>注意</span></span><span><span>: </span></span><span><span>更改对象名的任一部分都可能破坏脚本和存储过程。</span></span><span><br></span><span><span>cl[</span></span><span><span>把一台服务器上的数据库用户登录信息备份出来可以用</span></span><span><span>add_login_to_aserver</span></span><span><span>脚本</span></span><span><br><span>7. </span></span><span><span>查看链接服务器</span></span><span><br><span>sp_helplinkedsrvlogin</span></span><span></span></p>
<p><span><span>查看远端数据库用户登录信息</span></span><span><br><span>sp_helpremotelogin</span> <br></span><span><span>P<span>
<hr align=left width="33%" SIZE=1>
</span></span></span><span><span>8.</span></span><span><span>查看某数据库下某个数据对象的大小</span></span><span><br><span>sp_spaceused @objname</span><br></span><span><span>&shy;</span></span><span><span>还可以用</span></span><span><span>sp_toptables</span></span><span><span>过程看最大的</span></span><span><span>N(</span></span><span><span>默认为</span></span><span><span>50)</span></span><span><span>个表</span></span><span></span>
<p>&#160;</p>
<p align=left><span><span>查看某数据库下某个数据对象的索引信息</span></span><span><br><span>sp_helpindex&nbsp;@objname </span></span><span><span>/.&shy;</span></span><span><span>还可以用</span></span><span><span>SP_NChelpindex</span></span><span><span>过程查看更详细的索引情况</span></span><span><br><span>SP_NChelpindex @objname</span> <br><span>clustered</span></span><span><span>索引是把记录按物理顺序排列的，索引占的空间比较少。</span></span><span></span></p>
<p align=left><span><span>对键值</span></span><span><span>DML</span></span><span><span>操作十分频繁的表我建议用非</span></span><span><span>clustered</span></span><span><span>索引和约束，</span></span><span><span>fillfactor</span></span><span><span>参数都用默认值。</span></span><span><br></span><span><span>查看某数据库下某个数据对象的的约束信息</span></span><span><br><span>sp_helpconstraint @objname</span> <br></span><span><span>l</span></span><span><span>9.</span></span><span><span>查看数据库里所有的存储过程和函数</span></span><span><br><span>use @database_name</span></span><span></span></p>
<p align=left><span><span>sp_stored_procedures</span></span><span><br></span><span><span>查看存储过程和函数的源代码</span></span><span><br><span>sp_helptext ''@procedure_name''</span></span><span></span></p>
<p align=left><span><span>查看包含某个字符串</span></span><span><span>@str</span></span><span><span>的数据对象名称</span></span><span><br><span>select distinct object_name(id) from syscomments where text like ''%@str%''</span></span><span></span></p>
<p align=left><span><span>创建加密的存储过程或函数在</span></span><span><span>AS</span></span><span><span>前面加</span></span><span><span>WITH ENCRYPTION</span></span><span><span>参数</span></span><span></span></p>
<p align=left><span><span>解密加密过的存储过程和函数可以用</span></span><span><span>sp_decrypt</span></span><span><span>过程</span></span><span><br><span>10.</span></span><span><span>查看数据库里用户和进程的信息</span></span><span><br><span>sp_who</span><br></span><span><span>查看</span></span><span><span>SQL Server</span></span><span><span>数据库里的活动用户和进程的信息</span></span><span><br><span>sp_who ''active''</span> <br></span><span><span>查看</span></span><span><span>SQL Server</span></span><span><span>数据库里的锁的情况</span></span><span><br><span>sp_lock</span></span><span></span></p>
<p align=left><span><span>进程号</span></span><span><span>1--50</span></span><span><span>是</span></span><span><span>SQL Server</span></span><span><span>系统内部用的</span></span><span><span>,</span></span><span><span>进程号大于</span></span><span><span>50</span></span><span><span>的才是用户的连接进程</span></span><span><br><span>spid</span></span><span><span>是进程编号</span></span><span><span>,dbid</span></span><span><span>是数据库编号</span></span><span><span>,objid</span></span><span><span>是数据对象编号</span></span><span><br></span><span><span>查看进程正在执行的</span></span><span><span>SQL</span></span><span><span>语句</span></span><span><br><span>dbcc inputbuffer ()</span></span><span></span></p>
<p align=left><span><span>推荐大家用经过改进后的</span></span><span><span>sp_who3</span></span><span><span>过程可以直接看到进程运行的</span></span><span><span>SQL</span></span><span><span>语句</span></span><span><br><span>sp_who3</span></span><span></span></p>
<p align=left><span><span>检查死锁用</span></span><span><span>sp_who_lock</span></span><span><span>过程</span></span><span><br><span>sp_who_lock</span><br><span>11.</span></span><span><span>收缩数据库日志文件的方法</span></span><span><br></span><span><span>收缩简单恢复模式数据库日志，收缩后</span></span><span><span>@database_name_log</span></span><span><span>的大小单位为</span></span><span><span>M</span></span><span><br><span>backup log @database_name with no_log</span><br><span>dbcc shrinkfile (@database_name_log, 5)</span> <br><span>12.</span></span><span><span>分析</span></span><span><span>SQL Server SQL </span></span><span><span>语句的方法：</span></span><span><br><span>set statistics time {on | off}</span><br><span>set statistics io {on | off}</span><br></span><span><span>图形方式显示查询执行计划</span></span><span><span> </span></span><span><span>Il1_&amp;%`N4u </span></span><span>&nbsp;</span><span><span>在查询分析器</span></span><span><span>-&gt;</span></span><span><span>查询</span></span><span><span>-&gt;</span></span><span><span>显示估计的评估计划</span></span><span><span>(D)-Ctrl-L </span></span><span><span>或者点击工具栏里的图形</span></span><span></span></p>
<p align=left><span><span>文本方式显示查询执行计划</span></span><span><br><span>set showplan_all {on | off}</span></span><span></span></p>
<p align=left><span><span>&nbsp;set showplan_text { on | off }</span></span><span><br><span>set statistics profile { on | off }</span><br><span>13.</span></span><span><span>出现不一致错误时，</span></span><span><span>NT</span></span><span><span>事件查看器里出</span></span><span><span>3624</span></span><span><span>号错误，修复数据库的方法</span></span><span><span> </span></span><span><span>HS[[3ks+ </span></span><span>&nbsp;</span><span><span>先注释掉应用程序里引用的出现不一致性错误的表，然后在备份或其它机器上先恢复然后做修复操作</span></span><span><br></span><span><span>l</span></span><span><span>alter database [@error_database_name] set single_user</span></span><span> <br></span><span><span>x/pJoz&shy;</span></span><span><span>修复出现不一致错误的表</span></span><span><br><span>dbcc checktable(''@error_table_name'',repair_allow_data_loss)</span></span><span></span></p>
<p align=left><span><span>或者可惜选择修复出现不一致错误的小型数据库名</span></span><span><br><span>dbcc checkdb(''@error_database_name'',repair_allow_data_loss)</span> <br><span>alter database [@error_database_name] set multi_user</span><br><span>CHECKDB </span></span><span><span>有</span></span><span><span>3</span></span><span><span>个参数：</span></span><span><br><span>repair_allow_data_loss </span></span><span><span>包括对行和页进行分配和取消分配以改正分配错误、结构行或页的错误，</span></span><span><br></span><span><span>以及删除已损坏的文本对象，这些修复可能会导致一些数据丢失。</span></span><span><br></span><span><span>修复操作可以在用户事务下完成以允许用户回滚所做的更改。</span></span><span><br></span><span><span>如果回滚修复，则数据库仍会含有错误，应该从备份进行恢复。</span></span><span><br></span><span><span>如果由于所提供修复等级的缘故遗漏某个错误的修复，则将遗漏任何取决于该修复的修复。</span></span><span><br></span><span><span>修复完成后，请备份数据库。</span></span><span><br><span>repair_fast </span></span><span><span>进行小的、不耗时的修复操作，如修复非聚集索引中的附加键。</span></span><span><br></span><span><span>这些修复可以很快完成，并且不会有丢失数据的危险。</span></span><span><span>、</span></span><span><br><span>repair_rebuild </span></span><span><span>执行由</span></span><span><span> repair_fast </span></span><span><span>完成的所有修复，包括需要较长时间的修复（如重建索引）。</span></span><span></span></p>
<p align=left><span><span>执行这些修复时不会有丢失数据的危险。</span></span></p>
</span></span>
<img src ="http://www.cnitblog.com/malan11/aggbug/31144.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 13:39 <a href="http://www.cnitblog.com/malan11/articles/31144.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL SERVER的数据类型</title><link>http://www.cnitblog.com/malan11/articles/31141.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 05:16:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31141.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31141.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31141.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31141.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31141.html</trackback:ping><description><![CDATA[&nbsp; <span>1.SQL SERVER</span><span>的数据类型</span><span> </span>
<p align=left><span>　　数据类弄是数据的一种属性，表示数据所表示信息的类型。任何一种计算机语言都定义了自己的数据类型。当然，不同的程序语言都具有不同的特点，所定义的数据类型的各类和名称都或多或少有些不同。</span><span>SQLServer </span><span>提供了</span><span> 25 </span><span>种数据类型：</span></p>
<p align=left><span>Binary [(n)] </span></p>
<p align=left><span>Varbinary [(n)] </span></p>
<p align=left><span>Char [(n)] </span></p>
<p align=left><span>Varchar[(n)] </span></p>
<p align=left><span>Nchar[(n)] </span></p>
<p align=left><span>Nvarchar[(n)] </span></p>
<p align=left><span>Datetime </span></p>
<p align=left><span>Smalldatetime </span></p>
<p align=left><span>Decimal[(p[,s])] </span></p>
<p align=left><span>Numeric[(p[,s])] </span></p>
<p align=left><span>Float[(n)] </span></p>
<p align=left><span>Real </span></p>
<p align=left><span>Int </span></p>
<p align=left><span>Smallint </span></p>
<p align=left><span>Tinyint </span></p>
<p align=left><span>Money </span></p>
<p align=left><span>Smallmoney </span></p>
<p align=left><span>Bit </span></p>
<p align=left><span>Cursor </span></p>
<p align=left><span>Sysname </span></p>
<p align=left><span>Timestamp </span></p>
<p align=left><span>Uniqueidentifier </span></p>
<p align=left><span>Text </span></p>
<p align=left><span>Image </span></p>
<p align=left><span>Ntext </span></p>
<p align=left><span>(1)</span><span>二进制数据类型</span><span> </span></p>
<p align=left><span>　　二进制数据包括</span><span> Binary</span><span>、</span><span>Varbinary </span><span>和</span><span> Image<br></span><span>　　</span><span>Binary </span><span>数据类型既可以是固定长度的</span><span>(Binary),</span><span>也可以是变长度的。</span><span><br></span><span>　　</span><span>Binary[(n)] </span><span>是</span><span> n </span><span>位固定的二进制数据。其中，</span><span>n </span><span>的取值范围是从</span><span> 1 </span><span>到</span><span> 8000</span><span>。其存储窨的大小是</span><span> n + 4 </span><span>个字节。</span><span><br></span><span>　　</span><span>Varbinary[(n)] </span><span>是</span><span> n </span><span>位变长度的二进制数据。其中，</span><span>n </span><span>的取值范围是从</span><span> 1 </span><span>到</span><span> 8000</span><span>。其存储窨的大小是</span><span> n + 4</span><span>个字节，不是</span><span>n </span><span>个字节。</span><span><br></span><span>　　在</span><span> Image </span><span>数据类型中存储的数据是以位字符串存储的，不是由</span><span> SQL Server </span><span>解释的，必须由应用程序来解释。例如，应用程序可以使用</span><span>BMP</span><span>、</span><span>TIEF</span><span>、</span><span>GIF </span><span>和</span><span> JPEG </span><span>格式把数据存储在</span><span> Image </span><span>数据类型中。</span><span> </span></p>
<p align=left><span>(2)</span><span>字符数据类型</span><span> </span></p>
<p align=left><span>　　字符数据的类型包括</span><span> Char</span><span>，</span><span>Varchar </span><span>和</span><span> Text<br></span><span>　　字符数据是由任何字母、符号和数字任意组合而成的数据。</span><span><br></span><span>　　</span><span>Varchar </span><span>是变长字符数据，其长度不超过</span><span> 8KB</span><span>。</span><span>Char </span><span>是定长字符数据，其长度最多为</span><span> 8KB</span><span>。超过</span><span> 8KB </span><span>的</span><span>ASCII </span><span>数据可以使用</span><span>Text</span><span>数据类型存储。例如，因为</span><span> Html </span><span>文档全部都是</span><span> ASCII </span><span>字符，并且在一般情况下长度超过</span><span> 8KB</span><span>，所以这些文档可以</span><span> Text </span><span>数据类型存储在</span><span>SQL Server </span><span>中。</span><span> </span></p>
<p align=left><span>(3)Unicode </span><span>数据类型</span><span> </span></p>
<p align=left><span>　　</span><span>Unicode </span><span>数据类型包括</span><span> Nchar,Nvarchar </span><span>和</span><span>Ntext<br></span><span>　　在</span><span> Microsoft SQL Server </span><span>中，传统的非</span><span> Unicode </span><span>数据类型允许使用由特定字符集定义的字符。在</span><span> SQL Server</span><span>安装过程中，允许选择一种字符集。使用</span><span> Unicode </span><span>数据类型，列中可以存储任何由</span><span>Unicode </span><span>标准定义的字符。在</span><span> Unicode </span><span>标准中，包括了以各种字符集定义的全部字符。使用</span><span>Unicode</span><span>数据类型，所战胜的窨是使用非</span><span> Unicode </span><span>数据类型所占用的窨大小的两倍。</span><span> <br></span><span>　　在</span><span> SQL Server </span><span>中，</span><span>Unicode </span><span>数据以</span><span> Nchar</span><span>、</span><span>Nvarchar </span><span>和</span><span> Ntext </span><span>数据类型存储。使用这种字符类型存储的列可以存储多个字符集中的字符。当列的长度变化时，应该使用</span><span>Nvarchar </span><span>字符类型，这时最多可以存储</span><span> 4000 </span><span>个字符。当列的长度固定不变时，应该使用</span><span> Nchar </span><span>字符类型，同样，这时最多可以存储</span><span>4000 </span><span>个字符。当使用</span><span> Ntext </span><span>数据类型时，该列可以存储多于</span><span> 4000 </span><span>个字符。</span><span> </span></p>
<p align=left><span>(4)</span><span>日期和时间数据类型</span><span> </span></p>
<p align=left><span>　　日期和时间数据类型包括</span><span> Datetime </span><span>和</span><span> Smalldatetime</span><span>两种类型</span><span><br></span><span>　　日期和时间数据类型由有效的日期和时间组成。例如，有效的日期和时间数据包括</span><span>&#8220;4/01/98 12:15:00:00:00 PM&#8221;</span><span>和</span><span>&#8220;1:28:29:15:01<st1:chsdate w:st="on" Year="1998" Month="8" Day="17" IsLunarDate="False" IsROCDate="False">AM 8/17/98</st1:chsdate>&#8221;</span><span>。前一个数据类型是日期在前，时间在后一个数据类型是霎时间在前，日期在后。在</span><span> Microsoft SQL Server</span><span>中，日期和时间数据类型包括</span><span>Datetime </span><span>和</span><span> Smalldatetime </span><span>两种类型时，所存储的日期范围是从</span><span> 1753 </span><span>年</span><span> 1 </span><span>月</span><span> 1 </span><span>日开始，到</span><span>9999 </span><span>年</span><span>12 </span><span>月</span><span> 31 </span><span>日结束</span><span>(</span><span>每一个值要求</span><span> 8 </span><span>个存储字节</span><span>)</span><span>。使用</span><span> Smalldatetime </span><span>数据类型时，所存储的日期范围是</span><span> 1900</span><span>年</span><span> 1 </span><span>月</span><span> 1</span><span>日</span><span> </span><span>开始，到</span><span> 2079 </span><span>年</span><span> 12 </span><span>月</span><span> 31 </span><span>日结束</span><span>(</span><span>每一个值要求</span><span> 4 </span><span>个存储字节</span><span>)</span><span>。</span><span><br></span><span>　　日期的格式可以设定。设置日期格式的命令如下：</span><span><br></span><span>　　</span><span>Set DateFormat {format | @format _var|<br></span><span>　　其中，</span><span>format | @format_var </span><span>是日期的顺序。有效的参数包括</span><span> MDY</span><span>、</span><span>DMY</span><span>、</span><span>YMD</span><span>、</span><span>YDM</span><span>、</span><span>MYD </span><span>和</span><span> DYM</span><span>。在默认情况下，日期格式为</span><span>MDY</span><span>。</span><span><br></span><span>　　例如，当执行</span><span> Set DateFormat YMD </span><span>之后，日期的格式为年</span><span> </span><span>月</span><span> </span><span>日</span><span> </span><span>形式；当执行</span><span> Set DateFormat DMY </span><span>之后，日期的格式为日</span><span> </span><span>月有年</span><span> </span><span>形式</span><span> </span></p>
<p align=left><span>（</span><span>5</span><span>）数字数据类型</span><span> </span></p>
<p align=left><span>　　数字数据只包含数字。数字数据类型包括正数和负数、小数（浮点数）和整数</span><span><br></span><span>　　整数由正整数和负整数组成，例如</span><span> 39</span><span>、</span><span>25</span><span>、</span><span>0-2 </span><span>和</span><span> 33967</span><span>。在</span><span> Micrsoft SQL Server </span><span>中，整数存储的数据类型是</span><span> </span><span>　　</span><span> Int</span><span>，</span><span>Smallint</span><span>和</span><span> Tinyint</span><span>。</span><span>Int </span><span>数据类型存储数据的范围大于</span><span> Smallint </span><span>数据类型存储数据的范围，而</span><span> Smallint </span><span>据类型存储数据的范围大于</span><span>Tinyint </span><span>数据类型存储数据的范围。使用</span><span> Int </span><span>数据狗昔存储数据的范围是从</span><span> -2 147 483 648 </span><span>到</span><span> 2 147 483 647</span><span>（每一个值要求</span><span>4</span><span>个字节存储空间）。使用</span><span> Smallint </span><span>数据类型时，存储数据的范围从</span><span> -32 768 </span><span>到</span><span> 32 767</span><span>（每一个值要求</span><span>2</span><span>个字节存储空间）。使用</span><span>Tinyint </span><span>数据类型时，存储数据的范围是从</span><span>0 </span><span>到</span><span>255</span><span>（每一个值要求</span><span>1</span><span>个字节存储空间）。</span><span><br></span><span>　　精确小娄数据在</span><span> SQL Server </span><span>中的数据类型是</span><span> <span>Decimal </span></span><span>和</span><span> Numeric</span><span>。这种数据所占的存储空间根据该数据的位数后的位数来确定。</span><span><br></span><span>　　在</span><span>SQL Server </span><span>中，近似小数数据的数据类型是</span><span> Float </span><span>和</span><span> Real</span><span>。例如，三分之一这个分数记作。</span><span>3333333</span><span>，当使用近似数据类型时能准确表示。因此，从系统中检索到的数据可能与存储在该列中数据不完全一样。</span><span> </span></p>
<p align=left><span>（</span><span>6</span><span>）货币数据表示正的或者负的货币数量</span><span> </span><span>。</span><span> </span></p>
<p align=left><span>　　在</span><span> Microsoft SQL Server </span><span>中，货币数据的数据类型是</span><span>Money </span><span>和</span><span> Smallmoney </span></p>
<p align=left><span>　　</span><span>Money</span><span>数据类型要求</span><span> 8 </span><span>个存储字节，</span><span>Smallmoney </span><span>数据类型要求</span><span> 4 </span><span>个存储字节。</span><span> </span></p>
<p align=left><span>（</span><span>7</span><span>）特殊数据类型</span><span> </span></p>
<p align=left><span>　　特殊数据类型包括前面没有提过的数据类型。特殊的数据类型有</span><span>3</span><span>种，即</span><span> </span><span>　　</span><span> Timestamp</span><span>、</span><span>Bit </span><span>和</span><span> Uniqueidentifier</span><span>。</span><span><br></span><span>　　</span><span>Timestamp </span><span>用于表示</span><span>SQL Server </span><span>活动的先后顺序，以二进投影的格式表示。</span><span>Timestamp </span><span>数据与插入数据或者日期和时间没有关系。</span><span><br></span><span>　　</span><span>Bit </span><span>由</span><span> 1 </span><span>或者</span><span> 0 </span><span>组成。当表示真或者假、</span><span>ON </span><span>或者</span><span> OFF </span><span>时，使用</span><span> Bit </span><span>数据类型。例如，询问是否是每一次访问的客户机请求可以存储在这种数据类型的列中。</span><span><br></span><span>　　</span><span>Uniqueidentifier </span><span>由</span><span> 16 </span><span>字节的十六进制数字组成，表示一个全局唯一的。当表的记录行要求唯一时，</span><span>GUID</span><span>是非常有用。例如，在客户标识号列使用这种数据类型可以区别不同的客户。</span><span> </span></p>
<p align=left><span>2.</span><span>用户定义的数据类型</span><span> </span></p>
<p align=left><span>　　用户定义的数据类型基于在</span><span> Microsoft SQL Server </span><span>中提供的数据类型。当几个表中必须存储同一种数据类型时，并且为保证这些列有相同的数据类型、长度和可空性时，可以使用用户定义的数据类型。例如，可定义一种称为</span><span> </span><span>　　</span><span>postal_code </span><span>的数据类型，它基于</span><span> Char </span><span>数据类型。</span><span><br></span><span>　　当创建用户定义的数据类型时，必须提供三个数：数据类型的名称、所基于的系统数据类型和数据类型的可空性。</span><span> </span></p>
<p align=left><span>（</span><span>1</span><span>）创建用户定义的数据类型</span><span> </span></p>
<p align=left><span>　　创建用户定义的数据类型可以使用</span><span> Transact-SQL </span><span>语句。系统存储过程</span><span> sp_addtype </span><span>可以来创建用户定义的数据类型。其语法形式如下：</span><span><br></span><span>　　</span><span>sp_addtype {type},[,system_data_bype][,'null_type']<br></span><span>　　其中，</span><span>type </span><span>是用户定义的数据类型的名称。</span><span>system_data_type </span><span>是系统提供的数据类型，例如</span><span> Decimal</span><span>、</span><span>Int</span><span>、</span><span>Char </span><span>　　等等。</span><span> null_type </span><span>表示该数据类型是如何处理空值的，必须使用单引号引起来，例如</span><span>'NULL'</span><span>、</span><span>'NOT NULL'</span><span>或者</span><span>'NONULL'</span><span>。</span><span><br></span><span>　　例子：</span><span><br></span><span>　　</span><span>Use cust<br></span><span>　　</span><span>Exec sp_addtype ssn,'Varchar(11)',"Not Null'<br></span><span>　　创建一个用户定义的数据类型</span><span> ssn</span><span>，其基于的系统数据类型是变长为</span><span>11 </span><span>的字符，不允许空。</span><span><br></span><span>　　例子：</span><span><br></span><span>　　</span><span>Use cust<br></span><span>　　</span><span>Exec sp_addtype birthday,datetime,'Null'<br></span><span>　　创建一个用户定义的数据类型</span><span> birthday</span><span>，其基于的系统数据类型是</span><span> DateTime</span><span>，允许空。</span><span><br></span><span>　　例子：</span><span><br></span><span>　　</span><span>Use master<br></span><span>　　</span><span>Exec sp_addtype telephone,'varchar(24),'Not Null'<br></span><span>　　</span><span>Eexc sp_addtype fax,'varchar(24)','Null'<br></span><span>　　创建两个数据类型，即</span><span> telephone </span><span>和</span><span> fax </span></p>
<p align=left><span>（</span><span>2</span><span>）删除用户定义的数据类型</span><span> </span></p>
<p align=left><span>　　当用户定义的数据类型不需要时，可删除。删除用户定义的数据类型的命令是</span><span> sp_droptype {'type'}</span><span>。</span><span><br></span><span>　　例子：</span><span><br></span><span>　　</span><span>Use master<br></span><span>　　</span><span>Exec sp_droptype 'ssn'<br></span><span>　　注意：当表中的列还正在使用用户定义的数据类型时，或者在其上面还绑定有默认或者规则时，这种用户定义的数据类型不能删除。</span><span> </span></p>
<p align=left><span>SQL SERVER</span><span>的字段类型说明</span><span> </span></p>
<p align=left><span>　　以下为</span><span>SQL SERVER7.0</span><span>以上版本的字段类型说明。</span><span>SQL SERVER6.5</span><span>的字段类型说明请参考</span><span>SQL SERVER</span><span>提供的说明。</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td width="20%">
            <p align=left><span>字段类型</span></p>
            </td>
            <td width="80%">
            <p align=left><span>描述</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;bit</span></p>
            </td>
            <td width="80%">
            <p align=left><span>&nbsp;0</span><span>或</span><span>1</span><span>的整型数字</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;int</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><span>-2^31(-2,147,483,648)</span><span>到</span><span>2^31(2,147,483,647)</span><span>的整型数字</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;smallint</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><span>-2^15(-32,768)</span><span>到</span><span>2^15(32,767)</span><span>的整型数字</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;tinyint</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><span>0</span><span>到</span><span>255</span><span>的整型数字</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left>&nbsp;</p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;decimal</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><span>-10^38</span><span>到</span><span>10^38-1</span><span>的定精度与有效位数的数字</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;numeric</span></p>
            </td>
            <td width="80%">
            <p align=left><span>&nbsp;decimal</span><span>的同义词</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left>&nbsp;</p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;money</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><span>-2^63(-922,337,203,685,477.5808)</span><span>到</span><span>2^63-1(922,337,203,685,477.5807)</span><span>的货币数据，最小货币单位千分之十</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;smallmoney</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><span>-214,748.3648</span><span>到</span><span>214,748.3647</span><span>的货币数据，最小货币单位千分之十</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left>&nbsp;</p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;float</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><span>-1.79E+308</span><span>到</span><span>1.79E+308</span><span>可变精度的数字</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;real</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><span>-3.04E+38</span><span>到</span><span>3.04E+38</span><span>可变精度的数字</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left>&nbsp;</p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;datetime</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><st1:chsdate w:st="on" Year="1753" Month="1" Day="1" IsLunarDate="False" IsROCDate="False"><span>1753</span><span>年</span><span>1</span><span>月</span><span>1</span><span>日</span></st1:chsdate><span>到</span><span>9999</span><span>年</span><span>12</span><span>日</span><span>31</span><span>的日期和时间数据，最小时间单位为百分之三秒或</span><span>3.33</span><span>毫秒</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;smalldatetime</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>从</span><st1:chsdate w:st="on" Year="1900" Month="1" Day="1" IsLunarDate="False" IsROCDate="False"><span>1900</span><span>年</span><span>1</span><span>月</span><span>1</span><span>日</span></st1:chsdate><span>到</span><st1:chsdate w:st="on" Year="2079" Month="6" Day="6" IsLunarDate="False" IsROCDate="False"><span>2079</span><span>年</span><span>6</span><span>月</span><span>6</span><span>日</span></st1:chsdate><span>的日期和时间数据，最小时间单位为分钟</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left>&nbsp;</p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;timestamp</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>时间戳，一个数据库宽度的唯一数字</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;uniqueidentifier</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>全球唯一标识符</span><span>GUID</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left>&nbsp;</p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;char</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>定长非</span><span>Unicode</span><span>的字符型数据，最大长度为</span><span>8000</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;varchar</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>变长非</span><span>Unicode</span><span>的字符型数据，最大长度为</span><span>8000</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;text</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>变长非</span><span>Unicode</span><span>的字符型数据，最大长度为</span><span>2^31-1(<st1:chmetcnv TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="2" UnitName="g" w:st="on">2G</st1:chmetcnv>)</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left>&nbsp;</p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;nchar</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>定长</span><span>Unicode</span><span>的字符型数据，最大长度为</span><span>8000</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;nvarchar</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>变长</span><span>Unicode</span><span>的字符型数据，最大长度为</span><span>8000</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;ntext</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>变长</span><span>Unicode</span><span>的字符型数据，最大长度为</span><span>2^31-1(<st1:chmetcnv TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="2" UnitName="g" w:st="on">2G</st1:chmetcnv>)</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left>&nbsp;</p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;binary</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>定长二进制数据，最大长度为</span><span>8000</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;varbinary</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>变长二进制数据，最大长度为</span><span>8000</span></p>
            </td>
        </tr>
        <tr>
            <td width="20%">
            <p align=left><span>&nbsp;image</span></p>
            </td>
            <td width="80%">
            <p align=left>&nbsp;<span>变长二进制数据，最大长度为</span><span>2^31-1(<st1:chmetcnv TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="2" UnitName="g" w:st="on">2G</st1:chmetcnv>)</span></p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cnitblog.com/malan11/aggbug/31141.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 13:16 <a href="http://www.cnitblog.com/malan11/articles/31141.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>精妙的SQL语句</title><link>http://www.cnitblog.com/malan11/articles/31140.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 05:07:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31140.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31140.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31140.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31140.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31140.html</trackback:ping><description><![CDATA[&nbsp;
<div>
<p align=left><span>说明：复制表</span><span>(</span><span>只复制结构</span><span>,</span><span>源表名：</span><span>a </span><span>新表名：</span><span>b) <br>select * into b from a where 1&lt;&gt;1</span></p>
<p align=left><span>说明：拷贝表</span><span>(</span><span>拷贝数据</span><span>,</span><span>源表名：</span><span>a </span><span>目标表名：</span><span>b)<br>insert into b(a, b, c) select d,e,f from b;</span></p>
<p align=left><span>说明：显示文章、提交人和最后回复时间</span><span><br>select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b</span></p>
<p align=left><span>说明：外连接查询</span><span>(</span><span>表名</span><span>1</span><span>：</span><span>a </span><span>表名</span><span>2</span><span>：</span><span>b)<br>select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c</span></p>
<p align=left><span>说明：日程安排提前五分钟提醒</span><span><br>select * from </span><span>日程安排</span><span> where datediff('minute',f</span><span>开始时间</span><span>,getdate())&gt;5</span></p>
<p align=left><span>说明：两张关联表，删除主表中已经在副表中没有的信息</span><span><br>delete from info where not exists ( select * from infobz where info.infid=infobz.infid )</span></p>
<p align=left><span>说明：</span><span>-- <br>SQL: <br>SELECT A.NUM, A.NAME, B.UPD_DATE, B.PREV_UPD_DATE <br>FROM TABLE1, <br>(SELECT X.NUM, X.UPD_DATE, Y.UPD_DATE PREV_UPD_DATE <br>FROM (SELECT NUM, UPD_DATE, INBOUND_QTY, STOCK_ONHAND <br>FROM TABLE2 <br>WHERE TO_CHAR(UPD_DATE,'YYYY/MM') = TO_CHAR(SYSDATE, 'YYYY/MM')) X, <br>(SELECT NUM, UPD_DATE, STOCK_ONHAND <br>FROM TABLE2 <br>WHERE TO_CHAR(UPD_DATE,'YYYY/MM') = <br>TO_CHAR(TO_DATE(TO_CHAR(SYSDATE, 'YYYY/MM') || '/01','YYYY/MM/DD') - 1, 'YYYY/MM') ) Y, <br>WHERE X.NUM = Y.NUM </span><span>（</span><span>+</span><span>）</span><span> <br>AND X.INBOUND_QTY + NVL(Y.STOCK_ONHAND,0) &lt;&gt; X.STOCK_ONHAND ) B <br>WHERE A.NUM = B.NUM</span></p>
<p align=left><span>说明：</span><span>-- <br>select * from studentinfo where not exists(select * from student where studentinfo.id=student.id) and </span><span>系名称</span><span>='"&amp;strdepartmentname&amp;"' and </span><span>专业名称</span><span>='"&amp;strprofessionname&amp;"' order by </span><span>性别</span><span>,</span><span>生源地</span><span>,</span><span>高考总成绩</span></p>
<p align=left><span>从数据库中去一年的各单位电话费统计</span><span>(</span><span>电话费定额贺电化肥清单两个表来源）</span><span> <br>SELECT a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy') AS telyear, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '01', a.factration)) AS JAN, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '02', a.factration)) AS FRI, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '03', a.factration)) AS MAR, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '04', a.factration)) AS APR, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '05', a.factration)) AS MAY, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '06', a.factration)) AS JUE, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '07', a.factration)) AS JUL, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '08', a.factration)) AS AGU, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '09', a.factration)) AS SEP, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '10', a.factration)) AS OCT, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '11', a.factration)) AS NOV, <br>SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '12', a.factration)) AS DEC <br><br>FROM (SELECT a.userper, a.tel, a.standfee, b.telfeedate, b.factration <br>FROM TELFEESTAND a, TELFEE b <br>WHERE a.tel = b.telfax) a <br>GROUP BY a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy')</span></p>
<p align=left><span>说明：四表联查问题</span><span><br>select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where ..... </span></p>
<p align=left><span>说明：得到表中最小的未使用的</span><span>ID</span><span>号</span></p>
<p align=left><span>SELECT (CASE WHEN EXISTS(SELECT * FROM Handle b WHERE b.HandleID = 1) THEN MIN(HandleID) + 1 ELSE 1 END) as HandleID&nbsp; FROM Handle&nbsp;WHERE NOT HandleID IN (SELECT a.HandleID - 1 FROM Handle a)</span></p>
<p align=left><span>一个</span><span>SQL</span><span>语句的问题</span><span>:</span><span>行列转换</span><span><br>select * from v_temp<br></span><span>上面的视图结果如下</span><span>:<br>user_name role_name<br>-------------------------<br></span><span>系统管理员</span><span> </span><span>管理员</span><span> <br>feng </span><span>管理员</span><span> <br>feng </span><span>一般用户</span><span> <br>test </span><span>一般用户</span><span> <br></span><span>想把结果变成这样</span><span>:<br>user_name role_name<br>---------------------------<br></span><span>系统管理员</span><span> </span><span>管理员</span><span> <br>feng </span><span>管理员</span><span>,</span><span>一般用户</span><span> <br>test </span><span>一般用户</span><span><br>===================<br>create table a_test(name varchar(20),role2 varchar(20))<br>insert into a_test values('</span><span>李</span><span>','</span><span>管理员</span><span>')<br>insert into a_test values('</span><span>张</span><span>','</span><span>管理员</span><span>')<br>insert into a_test values('</span><span>张</span><span>','</span><span>一般用户</span><span>')<br>insert into a_test values('</span><span>常</span><span>','</span><span>一般用户</span><span>')<br>create function join_str(@content varchar(100))<br>returns varchar(2000)<br>as<br>begin<br>declare @str varchar(2000)<br>set @str=''<br>select @str=@str+','+rtrim(role2) from a_test where [name]=@content<br>select @str=right(@str,len(@str)-1)<br>return @str<br>end<br>go<br>--</span><span>调用：</span><span><br>select [name],dbo.join_str([name]) role2 from a_test group by [name]<br>--select distinct name,dbo.uf_test(name) from a_test</span></p>
<p align=left><span>快速比较结构相同的两表</span><span><br></span><span>结构相同的两表，一表有记录</span><span>3</span><span>万条左右，一表有记录</span><span>2</span><span>万条左右，我怎样快速查找两表的不同记录？</span><span><br>============================<br></span><span>给你一个测试方法，从</span><span>northwind</span><span>中的</span><span>orders</span><span>表取数据。</span><span><br>select * into n1 from orders<br>select * into n2 from orders<br>select * from n1<br>select * from n2<br>--</span><span>添加主键，然后修改</span><span>n1</span><span>中若干字段的若干条</span><span><br>alter table n1 add constraint pk_n1_id primary key (OrderID)<br>alter table n2 add constraint pk_n2_id primary key (OrderID)<br>select OrderID from (select * from n1 union select * from n2) a group by OrderID having count(*) &gt; 1<br></span><span>应该可以，而且将不同的记录的</span><span>ID</span><span>显示出来。</span><span><br></span><span>下面的适用于双方记录一样的情况，</span><span><br>select * from n1 where orderid in (select OrderID from (select * from n1 union select * from n2) a group by OrderID having count(*) &gt; 1) <br></span><span>至于双方互不存在的记录是比较好处理的</span><span><br>--</span><span>删除</span><span>n1,n2</span><span>中若干条记录</span><span><br>delete from n1 where orderID in ('10728','10730')<br>delete from n2 where orderID in ('11000','11001')<br>--*************************************************************<br>-- </span><span>双方都有该记录却不完全相同</span><span><br>select * from n1 where orderid in(select OrderID from (select * from n1 union select * from n2) a group by OrderID having count(*) &gt; 1)<br>union<br>--n2</span><span>中存在但在</span><span>n1</span><span>中不存的在</span><span>10728,10730<br>select * from n1 where OrderID not in (select OrderID from n2)<br>union<br>--n1</span><span>中存在但在</span><span>n2</span><span>中不存的在</span><span>11000,11001<br>select * from n2 where OrderID not in (select OrderID from n1)</span></p>
<p align=left><span>四种方法取表里</span><span>n</span><span>到</span><span>m</span><span>条纪录：</span><span><br>1.<br>select top m * into </span><span>临时表</span><span>(</span><span>或表变量</span><span>) from tablename order by columnname -- </span><span>将</span><span>top m</span><span>笔插入</span><span><br>set rowcount n<br>select * from </span><span>表变量</span><span> order by columnname desc<br>2.<br>select top n * from (select top m * from tablename order by columnname) a order by columnname desc<br><br>3.</span><span>如果</span><span>tablename</span><span>里没有其他</span><span>identity</span><span>列，那么：</span><span><br>select identity(int) id0,* into #temp from tablename<br></span><span>取</span><span>n</span><span>到</span><span>m</span><span>条的语句为：</span><span><br>select * from #temp where id0 &gt;=n and id0 &lt;= m<br></span><span>如果你在执行</span><span>select identity(int) id0,* into #temp from tablename</span><span>这条语句的时候报错</span><span>,</span><span>那是因为你的</span><span>DB</span><span>中间的</span><span>select into/bulkcopy</span><span>属性没有打开要先执行：</span><span><br>exec sp_dboption </span><span>你的</span><span>DB</span><span>名字</span><span>,'select into/bulkcopy',true<br>4.</span><span>如果表里有</span><span>identity</span><span>属性，那么简单：</span><span><br>select * from tablename where identitycol between n and m </span></p>
<p align=left><span>如何删除一个表中重复的记录？</span><span><br>create table a_dist(id int,name varchar(20))<br>insert into a_dist values(1,'abc')<br>insert into a_dist values(1,'abc')<br>insert into a_dist values(1,'abc')<br>insert into a_dist values(1,'abc')<br>exec up_distinct 'a_dist','id'<br>select * from a_dist<br>create procedure up_distinct(@t_name varchar(30),@f_key varchar(30))<br>--f_key</span><span>表示是分组字段﹐即主键字段</span><span><br>as<br>begin<br>declare @max integer,@id varchar(30) ,@sql varchar(7999) ,@type integer<br>select @sql = 'declare cur_rows cursor for select '+@f_key+' ,count(*) from ' +@t_name +' group by ' +@f_key +' having count(*) &gt; 1'<br>exec(@sql)<br>open cur_rows <br>fetch cur_rows into @id,@max <br>while @@fetch_status=0 <br>begin <br>select @max = @max -1 <br>set rowcount @max <br>select @type = xtype from syscolumns where id=object_id(@t_name) and name=@f_key<br>if @type=56<br>select @sql = 'delete from '+@t_name+' where ' + @f_key+' = '+ @id <br>if @type=167<br>select @sql = 'delete from '+@t_name+' where ' + @f_key+' = '+''''+ @id +'''' <br>exec(@sql)<br>fetch cur_rows into @id,@max <br>end <br>close cur_rows <br>deallocate cur_rows<br>set rowcount 0<br>end<br>select * from systypes<br>select * from syscolumns where id = object_id('a_dist')</span></p>
<p align=left><span>查询数据的最大排序问题（只能用一条语句写）</span><span> <br>CREATE TABLE hard (qu char (11) ,co char (11) ,je numeric(3, 0)) <br>insert into hard values ('A','1',3)<br>insert into hard values ('A','2',4)<br>insert into hard values ('A','4',2)<br>insert into hard values ('A','6',9)<br>insert into hard values ('B','1',4)<br>insert into hard values ('B','2',5)<br>insert into hard values ('B','3',6)<br>insert into hard values ('C','3',4)<br>insert into hard values ('C','6',7)<br>insert into hard values ('C','2',3)<br></span><span>要求查询出来的结果如下：</span><span><br>qu co je <br>----------- ----------- ----- <br>A 6 <st1:chmetcnv w:st="on" UnitName="a" SourceValue="9" HasSpace="True" Negative="False" NumberType="1" TCSC="0">9<br>A</st1:chmetcnv> 2 4<br>B 3 6<br>B 2 <st1:chmetcnv w:st="on" UnitName="C" SourceValue="5" HasSpace="True" Negative="False" NumberType="1" TCSC="0">5<br>C</st1:chmetcnv> 6 <st1:chmetcnv w:st="on" UnitName="C" SourceValue="7" HasSpace="True" Negative="False" NumberType="1" TCSC="0">7<br>C</st1:chmetcnv> 3 4<br></span><span>就是要按</span><span>qu</span><span>分组，每组中取</span><span>je</span><span>最大的前</span><span>2</span><span>位！！</span><span><br></span><span>而且只能用一句</span><span>sql</span><span>语句！！！</span><span><br>select * from hard a where je in (select top 2 je from hard b where a.qu=b.qu order by je) </span></p>
<p align=left><span>求删除重复记录的</span><span>sql</span><span>语句？</span><span> <br></span><span>怎样把具有相同字段的纪录删除，只留下一条。</span><span><br></span><span>例如，表</span><span>test</span><span>里有</span><span>id,name</span><span>字段</span><span><br></span><span>如果有</span><span>name</span><span>相同的记录</span><span> </span><span>只留下一条，其余的删除。</span><span><br>name</span><span>的内容不定，相同的记录数不定。</span><span><br></span><span>有没有这样的</span><span>sql</span><span>语句？</span><span><br>==============================<br>A:</span><span>一个完整的解决方案：</span><span><br></span><span>将重复的记录记入</span><span>temp1</span><span>表</span><span>:<br>select [</span><span>标志字段</span><span>id],count(*) into temp1 from [</span><span>表名</span><span>]<br>group by [</span><span>标志字段</span><span>id]<br>having count(*)&gt;1<br>2</span><span>、将不重复的记录记入</span><span>temp1</span><span>表</span><span>:<br>insert temp1 select [</span><span>标志字段</span><span>id],count(*) from [</span><span>表名</span><span>] group by [</span><span>标志字段</span><span>id] having count(*)=1<br>3</span><span>、作一个包含所有不重复记录的表：</span><span><br>select * into temp2 from [</span><span>表名</span><span>] where </span><span>标志字段</span><span>id in(select </span><span>标志字段</span><span>id from temp1)<br>4</span><span>、删除重复表</span><span>:<br>delete [</span><span>表名</span><span>]<br>5</span><span>、恢复表：</span><span><br>insert [</span><span>表名</span><span>] select * from temp2<br>6</span><span>、删除临时表</span><span>:<br>drop table temp1<br>drop table temp2<br>================================<br>B:<br>create table a_dist(id int,name varchar(20))<br>insert into a_dist values(1,'abc')<br>insert into a_dist values(1,'abc')<br>insert into a_dist values(1,'abc')<br>insert into a_dist values(1,'abc')<br>exec up_distinct 'a_dist','id'<br>select * from a_dist<br>create procedure up_distinct(@t_name varchar(30),@f_key varchar(30))<br>--f_key</span><span>表示是分组字段﹐即主键字段</span><span><br>as<br>begin<br>declare @max integer,@id varchar(30) ,@sql varchar(7999) ,@type integer<br>select @sql = 'declare cur_rows cursor for select '+@f_key+' ,count(*) from ' +@t_name +' group by ' +@f_key +' having count(*) &gt; 1'<br>exec(@sql)<br>open cur_rows <br>fetch cur_rows into @id,@max <br>while @@fetch_status=0 <br>begin <br>select @max = @max -1 <br>set rowcount @max <br>select @type = xtype from syscolumns where id=object_id(@t_name) and name=@f_key<br>if @type=56<br>select @sql = 'delete from '+@t_name+' where ' + @f_key+' = '+ @id <br>if @type=167<br>select @sql = 'delete from '+@t_name+' where ' + @f_key+' = '+''''+ @id +'''' <br>exec(@sql)<br>fetch cur_rows into @id,@max <br>end <br>close cur_rows <br>deallocate cur_rows<br>set rowcount 0<br>end<br><br>select * from systypes<br>select * from syscolumns where id = object_id('a_dist')</span></p>
<p align=left><span>行列转换</span><span>--</span><span>普通</span><span> <br></span><span>假设有张学生成绩表</span><span>(CJ)</span><span>如下</span><span> <br>Name Subject Result <br></span><span>张三</span><span> </span><span>语文</span><span> 80 <br></span><span>张三</span><span> </span><span>数学</span><span> 90 <br></span><span>张三</span><span> </span><span>物理</span><span> 85 <br></span><span>李四</span><span> </span><span>语文</span><span> 85 <br></span><span>李四</span><span> </span><span>数学</span><span> 92 <br></span><span>李四</span><span> </span><span>物理</span><span> 82 <br></span><span>想变成</span><span> <br></span><span>姓名</span><span> </span><span>语文</span><span> </span><span>数学</span><span> </span><span>物理</span><span> <br></span><span>张三</span><span> 80 90 85 <br></span><span>李四</span><span> 85 92 82 <br>declare @sql varchar(4000) <br>set @sql = 'select Name' <br>select @sql = @sql + ',sum(case Subject when '''+Subject+''' then Result end) ['+Subject+']' <br>from (select distinct Subject from CJ) as a <br>select @sql = @sql+' from test group by name' <br>exec(@sql) <br></span><span>行列转换</span><span>--</span><span>合并</span><span> <br></span><span>有表</span><span>A, <br>id pid <br>1 1 <br>1 2 <br>1 3 <br>2 1 <br>2 2 <br>3 1 <br></span><span>如何化成表</span><span>B: <br>id pid <br>1 1,2,3 <br>2 1,2 <br>3 1 <br></span><span>创建一个合并的函数</span><span> <br>create function fmerg(@id int) <br>returns varchar(8000) <br>as <br>begin <br>declare @str varchar(8000) <br>set @str='' <br>select @str=@str+','+cast(pid as varchar) from </span><span>表</span><span>A where id=@id <br>set @str=right(@str,len(@str)-1) <br>return(@str) <br>End <br>go <br>--</span><span>调用自定义函数得到结果</span><span> <br>select distinct id,dbo.fmerg(id) from </span><span>表</span><span>A </span></p>
<p align=left><span>如何取得一个数据表的所有列名</span><span> <br></span><span>方法如下：先从</span><span>SYSTEMOBJECT</span><span>系统表中取得数据表的</span><span>SYSTEMID,</span><span>然后再</span><span>SYSCOLUMN</span><span>表中取得该数据表的所有列名。</span><span> <br>SQL</span><span>语句如下：</span><span> <br>declare @objid int,@objname char(40) <br>set @objname = 'tablename' <br>select @objid = id from sysobjects where id = object_id(@objname) <br>select 'Column_name' = name from syscolumns where id = @objid order by colid <br></span><span>或</span><span><br>SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='users'</span></p>
<p align=left><span>通过</span><span>SQL</span><span>语句来更改用户的密码</span><span> <br></span><span>修改别人的</span><span>,</span><span>需要</span><span>sysadmin role <br>EXEC sp_password NULL, 'newpassword', 'User' <br></span><span>如果帐号为</span><span>SA</span><span>执行</span><span>EXEC sp_password NULL, 'newpassword', sa</span></p>
<p align=left><span>怎么判断出一个表的哪些字段不允许为空？</span><span> <br>select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where IS_NULLABLE='NO' and TABLE_NAME=tablename </span></p>
<p align=left><span>如何在数据库里找到含有相同字段的表？</span><span> <br>a. </span><span>查已知列名的情况</span><span> <br>SELECT b.name as TableName,a.name as columnname <br>From syscolumns a INNER JOIN sysobjects b <br>ON a.id=b.id <br>AND b.type='U' <br>AND a.name='</span><span>你的字段名字</span><span>' </span></p>
<p align=left><span>未知列名查所有在不同表出现过的列名</span><span> <br>Select o.name As tablename,s1.name As columnname <br>From syscolumns s1, sysobjects o <br>Where s1.id = o.id <br>And o.type = 'U' <br>And Exists ( <br>Select 1 From syscolumns s2 <br>Where s1.name = s2.name <br>And s1.id &lt;&gt; s2.id <br>) </span></p>
<p align=left><span>查询第</span><span>xxx</span><span>行数据</span><span> <br></span><span>假设</span><span>id</span><span>是主键：</span><span> <br>select * from (select top xxx * from yourtable) aa where not exists(select 1 from (select top xxx-1 * from yourtable) bb where aa.id=bb.id) <br></span><span>如果使用游标也是可以的</span><span> <br>fetch absolute [number] from [cursor_name] <br></span><span>行数为绝对行数</span><span> </span></p>
<p align=left><span>SQL Server</span><span>日期计算</span><span> <br>a. </span><span>一个月的第一天</span><span> <br>SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0) <br>b. </span><span>本周的星期一</span><span> <br>SELECT DATEADD(wk, DATEDIFF(wk,0,getdate()), 0) <br>c. </span><span>一年的第一天</span><span> <br>SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0) <br>d. </span><span>季度的第一天</span><span> <br>SELECT DATEADD(qq, DATEDIFF(qq,0,getdate()), 0) <br>e. </span><span>上个月的最后一天</span><span> <br>SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)) <br>f. </span><span>去年的最后一天</span><span> <br>SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)) <br>g. </span><span>本月的最后一天</span><span> <br>SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate())+1, 0)) <br>h. </span><span>本月的第一个星期一</span><span> <br>select DATEADD(wk, DATEDIFF(wk,0, <br>dateadd(dd,6-datepart(day,getdate()),getdate()) <br>), 0) <br>i. </span><span>本年的最后一天</span><span> <br>SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate())+1, 0))</span><span>。</span><span> </span></p>
<p align=left><span>获取表结构</span><span>[</span><span>把</span><span> 'sysobjects' </span><span>替换</span><span> </span><span>成</span><span> <span>'tablename' </span></span><span>即可</span><span>] <br>SELECT CASE IsNull(I.name, '') <br>When '' Then '' <br>Else '*' <br>End as IsPK, <br>Object_Name(A.id) as t_name, <br>A.name as c_name, <br>IsNull(SubString(M.text, 1, 254), '') as pbc_init, <br>T.name as F_DataType, <br>CASE IsNull(TYPEPROPERTY(T.name, 'Scale'), '') <br>WHEN '' Then Cast(A.prec as varchar) <br>ELSE Cast(A.prec as varchar) + ',' + Cast(A.scale as varchar) <br>END as F_Scale, <br>A.isnullable as F_isNullAble <br>FROM Syscolumns as A <br>JOIN Systypes as T <br>ON (A.xType = T.xUserType AND A.Id = Object_id('sysobjects') ) <br>LEFT JOIN ( SysIndexes as I <br>JOIN Syscolumns as A1 <br>ON ( I.id = A1.id and A1.id = object_id('sysobjects') and (I.status &amp; 0x800) = 0x800 AND A1.colid &lt;= I.keycnt) ) <br>ON ( A.id = I.id AND A.name = index_col('sysobjects', I.indid, A1.colid) ) <br>LEFT JOIN SysComments as M <br>ON ( M.id = A.cdefault and ObjectProperty(A.cdefault, 'IsConstraint') = 1 ) <br>ORDER BY A.Colid ASC</span></p>
<p align=left><span>提取数据库内所有表的字段详细说明的</span><span>SQL</span><span>语句</span><span> <br>SELECT <br>(case when a.colorder=1 then d.name else '' end) N'</span><span>表名</span><span>', <br>a.colorder N'</span><span>字段序号</span><span>', <br>a.name N'</span><span>字段名</span><span>', <br>(case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '&#8730;'else '' <br>end) N'</span><span>标识</span><span>', <br>(case when (SELECT count(*) <br>FROM sysobjects <br>WHERE (name in <br>(SELECT name <br>FROM sysindexes <br>WHERE (id = a.id) AND (indid in <br>(SELECT indid <br>FROM sysindexkeys <br>WHERE (id = a.id) AND (colid in <br>(SELECT colid <br>FROM syscolumns <br>WHERE (id = a.id) AND (name = a.name))))))) AND <br>(xtype = 'PK'))&gt;0 then '&#8730;' else '' end) N'</span><span>主键</span><span>', <br>b.name N'</span><span>类型</span><span>', <br>a.length N'</span><span>占用字节数</span><span>', <br>COLUMNPROPERTY(a.id,a.name,'PRECISION') as N'</span><span>长度</span><span>', <br>isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0) as N'</span><span>小数位数</span><span>', <br>(case when a.isnullable=1 then '&#8730;'else '' end) N'</span><span>允许空</span><span>', <br>isnull(e.text,'') N'</span><span>默认值</span><span>', <br>isnull(g.[value],'') AS N'</span><span>字段说明</span><span>' <br>FROM syscolumns a <br>left join systypes b <br>on a.xtype=b.xusertype <br>inner join sysobjects d <br>on a.id=d.id and d.xtype='U' and d.name&lt;&gt;'dtproperties' <br>left join syscomments e <br>on a.cdefault=e.id <br>left join sysproperties g <br>on a.id=g.id AND a.colid = g.smallid <br>order by object_name(a.id),a.colorder</span></p>
<p align=left><span>快速获取表</span><span>test</span><span>的记录总数</span><span>[</span><span>对大容量表非常有效</span><span>] <br></span><span>快速获取表</span><span>test</span><span>的记录总数</span><span>: <br>select rows from sysindexes where id = object_id('test') and indid in (0,1)<br>update 2 set KHXH=(ID+1)\2 2</span><span>行递增编号</span><span><br>update [23] set id1 = 'No.'+right('00000000'+id,6) where id not like 'No%' //</span><span>递增</span><span><br>update [23] set id1= 'No.'+right('00000000'+replace(id1,'No.',''),6) //</span><span>补位递增</span><span><br>delete from [1] where (id%2)=1 <br></span><span>奇数</span></p>
<p align=left><span>替换表名字段</span><span><br>update [1] set domurl = replace(domurl,'Upload/Imgswf/','Upload/Photo/') where domurl like '%Upload/Imgswf/%'</span></p>
<p align=left><span>截位</span><span><br>SELECT LEFT(</span><span>表名</span><span>, 5) </span></p>
<p align=left><span>判断表为空：</span></p>
<p align=left><span>select<span>&nbsp;&nbsp; </span>count(*)<span>&nbsp;&nbsp; </span>c<span>&nbsp;&nbsp; </span>from<span>&nbsp;&nbsp; </span>TJ_BJQKTjBB</span></p>
<p align=left><span>或</span></p>
<p align=left><span>if<span>&nbsp;&nbsp; </span>exists(select<span>&nbsp;&nbsp; </span>1<span>&nbsp;&nbsp; </span>from<span>&nbsp;&nbsp; </span>TJ_BJQKTjBB)<span>&nbsp;&nbsp; </span></span></p>
<p align=left><span>&nbsp;print<span>&nbsp;&nbsp; </span>'</span><span>不为空</span><span>'<span>&nbsp;&nbsp; </span></span></p>
<p align=left><span>&nbsp;else<span>&nbsp;&nbsp; </span></span></p>
<p align=left><span>&nbsp;print<span>&nbsp;&nbsp; </span>'</span><span>为空</span><span>' </span></p>
<p align=left><span>日期转换</span></p>
</div>
<p><span>select LSBH&nbsp;from BJSJ where&nbsp;(convert(char(20),AFSJ,112))&lt;'20060809'</span></p>
<div>
<p align=left><a name=Top><span>怎样用</span></a><span><span>group by</span></span><span><span>输出数据库某字段统计结果</span></span><span></span></p>
</div>
<p align=left><span>想将数据库中按编号统计出次数</span>&nbsp;<span>想使用</span><span>group &nbsp; by &nbsp; <br>&nbsp; </span><span>不会写语句</span>&nbsp;<span>请不吝赐教</span><span> &nbsp; <br>&nbsp; </span><span>数据库设计</span><span> &nbsp; <br>&nbsp; </span><span>字段</span><span>: &nbsp; ID(</span><span>主键</span><span>),</span><span>日期</span><span>,</span><span>部门</span><span>,</span><span>编号</span><span>,</span><span>姓名</span><span>,</span><span>次数</span><span> &nbsp; <br>&nbsp; </span><span>最好有个例子</span>&nbsp;<span>谢谢</span><span> </span></p>
<p align=left><a name=Reply_30850066><span>select &nbsp; </span></a><span><span>编号</span></span><span><span>, &nbsp; sum(</span></span><span><span>次数</span></span><span><span>) &nbsp; from &nbsp; TABLE1 &nbsp; group &nbsp; by &nbsp; </span></span><span><span>编号</span></span><span><span> &nbsp; <br>&nbsp; </span></span><span><span>好像是这样的</span></span><span><span>&#8230;&#8230; </span></span></p>
<p align=left><a name=Reply_30850071><span>select &nbsp; count(</span></a><span><span>次数</span></span><span><span>) &nbsp; from &nbsp; </span></span><span><span>表</span></span><span><span> &nbsp; where &nbsp; </span></span><span><span>条件</span></span><span><span> &nbsp; group &nbsp; by &nbsp; ID </span></span></p>
<p align=left><a name=Reply_30850120><span>补充：查询记录条数用</span></a><span><span>count(</span></span><span><span>次数），查询记录内容的总和就用</span></span><span><span>sum(</span></span><span><span>次数</span></span><span><span>) </span></span></p>
<span>select &nbsp; count(1) &nbsp; from &nbsp; </span><span>表</span><span> &nbsp; where &nbsp; </span><span>条件</span><span> &nbsp; group &nbsp; by &nbsp; ID &nbsp; <br>&nbsp; &nbsp; </span><span>更高效</span><span>&nbsp;&nbsp;</span>
<img src ="http://www.cnitblog.com/malan11/aggbug/31140.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 13:07 <a href="http://www.cnitblog.com/malan11/articles/31140.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL基本语法</title><link>http://www.cnitblog.com/malan11/articles/31139.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 05:00:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31139.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31139.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31139.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31139.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31139.html</trackback:ping><description><![CDATA[<strong>&nbsp; <span>一、</span><span> </span><span>简单查询</span></strong><span><br></span><span>　　简单的</span><span>Transact-SQL</span><span>查询只包括选择列表、</span><span>FROM</span><span>子句和</span><span>WHERE</span><span>子句。它们分别说明所查询列、查询的表或视图、以及搜索条件等。</span><span><br></span><span>　　</span>
<p align=left><span>例如，下面的语句查询</span><span>testtable</span><span>表中姓名为</span><span>&#8220;</span><span>张三</span><span>&#8221;</span><span>的</span><span>nickname</span><span>字段和</span><span>email</span><span>字段。</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span>SELECT nickname,email<br></span><span>　　</span><span>FROM testtable<br></span><span>　　</span><span>WHERE name='</span><span>张三</span><span>'</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><strong><span>(</span><span>一</span><span>) </span><span>选择列表</span></strong><span><br></span><span>　　选择列表</span><span>(select_list)</span><span>指出所查询列，它可以是一组列名列表、星号、表达式、变量</span><span>(</span><span>包括局部变量和全局变量</span><span>)</span><span>等构成。</span><span><br>1</span><span>、选择所有列</span><span><br></span><span>　　</span></p>
<p align=left><span>例如，下面语句显示</span><span>testtable</span><span>表中所有列的数据：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span><br></span><span>　　</span><span>SELECT *<br></span><span>　　</span><span>FROM testtable</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><strong><span>2</span><span>、选择部分列并指定它们的显示次序</span></strong><span><br></span><span>　</span></p>
<p align=left><span>&nbsp;</span><span>查询结果集合中数据的排列顺序与选择列表中所指定的列名排列顺序相同。例如：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span>SELECT nickname,email<br></span><span>　　</span><span>FROM testtable</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><strong><span>3</span><span>、更改列标题</span></strong><span><br></span><span>　　在选择列表中，可重新指定列标题。定义格式为：</span><span><br></span><span>　　列标题</span><span>=</span><span>列名</span><span><br></span><span>　　列名</span><span> </span><span>列标题</span><span><br><span>&nbsp;&nbsp; </span></span></p>
<p align=left><span>&nbsp;</span><span>如果指定的列标题不是标准的标识符格式时，应使用引号定界符，例如，下列语句使用汉字显示列标题：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span><br></span><span>　　</span><span>SELECT </span><span>昵称</span><span>=nickname,</span><span>电子邮件</span><span>=email<br></span><span>　　</span><span>FROM testtable</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><strong><span>4</span><span>、删除重复行</span></strong><span><br></span><span>　　</span><span>SELECT</span><span>语句中使用</span><span>ALL</span><span>或</span><span>DISTINCT</span><span>选项来显示表中符合条件的所有行或删除其中重复的数据行，默认为</span><span>ALL</span><span>。使用</span><span>DISTINCT</span><span>选项时，对于所有重复的数据行在</span><span>SELECT</span><span>返回的结果集合中只保留一行。</span><span><br>5</span><span>、限制返回的行数</span><span><br></span><span>　　使用</span><span>TOP n [PERCENT]</span><span>选项限制返回的数据行数，</span><span>TOP n</span><span>说明返回</span><span>n</span><span>行，而</span><span>TOP n PERCENT</span><span>时，说明</span><span>n</span><span>是表示一百分数，指定返回的行数等于总行数的百分之几。</span></p>
<p align=left><span>例如：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span>SELECT TOP 2 *FROM testtable SELECT TOP 20 PERCENT * FROM testtable</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><strong><span>(</span><span>二</span><span>) FROM</span><span>子句</span></strong><span><br></span><span>　　</span><span>FROM</span><span>子句指定</span><span>SELECT</span><span>语句查询及与查询相关的表或视图。在</span><span>FROM</span><span>子句中最多可指定</span><span>256</span><span>个表或视图，它们之间用逗号分隔。</span><span><br></span><span>　　</span></p>
<p align=left><span>在</span><span>FROM</span><span>子句同时指定多个表或视图时，如果选择列表中存在同名列，这时应使用对象名限定这些列所属的表或视图。例如在</span><span>usertable</span><span>和</span><span>citytable</span><span>表中同时存在</span><span>cityid</span><span>列，在查询两个表中的</span><span>cityid</span><span>时应使用下面语句格式加以限定：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span>SELECT username,citytable.cityid<br></span><span>　　</span><span>FROM usertable,citytable<br></span><span>　　</span><span>WHERE usertable.cityid=citytable.cityid</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left>&nbsp;</p>
<p align=left><span>在</span><span>FROM</span><span>子句中可用以下两种格式为表或视图指定别名：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span><br></span><span>　　表名</span><span> as </span><span>别名</span><span><br></span><span>　　表名</span><span> </span><span>别名</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><span>　　</span></p>
<p align=left><span>例如上面语句可用表的别名格式表示为：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span><br></span><span>　　</span><span>SELECT username,b.cityid<br></span><span>　　</span><span>FROM usertable a,citytable b<br></span><span>　　</span><span>WHERE a.cityid=b.cityid</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left>&nbsp;</p>
<p align=left><span>SELECT</span><span>不仅能从表或视图中检索数据，它还能够从其它查询语句所返回的结果集合中查询数据。例如：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span><br></span><span>　　</span><span>SELECT a.au_fname+a.au_lname<br></span><span>　　</span><span>FROM authors a,titleauthor ta<br></span><span>　　</span><span>(SELECT title_id,title<br></span><span>　　</span><span>FROM titles<br></span><span>　　</span><span>WHERE ytd_sales&gt;10000<br></span><span>　　</span><span>) AS t<br></span><span>　　</span><span>WHERE a.au_id=ta.au_id<br></span><span>　　</span><span>AND ta.title_id=t.title_id</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><span><br></span><span>此例中，将</span><span>SELECT</span><span>返回的结果集合给予一别名</span><span>t</span><span>，然后再从中检索数据。</span><span><br><strong>(</strong></span><strong><span>三</span><span>) </span><span>使用</span><span>WHERE</span><span>子句设置查询条件</span></strong><span><br></span><span>　　</span></p>
<p align=left><span>WHERE</span><span>子句设置查询条件，过滤掉不需要的数据行。例如下面语句查询年龄大于</span><span>20</span><span>的数据：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span><br></span><span>　　</span><span>SELECT *<br></span><span>　　</span><span>FROM usertable<br></span><span>　　</span><span>WHERE age&gt;20</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><span><br>WHERE</span><span>子句可包括各种条件运算符：</span><span><br></span><span>　　比较运算符</span><span>(</span><span>大小比较</span><span>)</span><span>：</span><span>&gt;</span><span>、</span><span>&gt;=</span><span>、</span><span>=</span><span>、</span><span>&lt;</span><span>、</span><span>&lt;=</span><span>、</span><span>&lt;&gt;</span><span>、</span><span>!&gt;</span><span>、</span><span>!&lt;<br></span><span>　　范围运算符</span><span>(</span><span>表达式值是否在指定的范围</span><span>)</span><span>：</span><span>BETWEEN&#8230;AND&#8230;<br></span><span>　　</span><span>NOT BETWEEN&#8230;AND&#8230;<br></span><span>　　列表运算符</span><span>(</span><span>判断表达式是否为列表中的指定项</span><span>)</span><span>：</span><span>IN (</span><span>项</span><span>1,</span><span>项</span><span>2&#8230;&#8230;)<br></span><span>　　</span><span>NOT IN (</span><span>项</span><span>1,</span><span>项</span><span>2&#8230;&#8230;)<br></span><span>　　模式匹配符</span><span>(</span><span>判断值是否与指定的字符通配格式相符</span><span>):LIKE</span><span>、</span><span>NOT LIKE<br></span><span>　　空值判断符</span><span>(</span><span>判断表达式是否为空</span><span>)</span><span>：</span><span>IS NULL</span><span>、</span><span>NOT IS NULL<br></span><span>　　逻辑运算符</span><span>(</span><span>用于多条件的逻辑连接</span><span>)</span><span>：</span><span>NOT</span><span>、</span><span>AND</span><span>、</span><span>OR<br>1</span><span>、范围运算符例：</span><span>age BETWEEN 10 AND 30</span><span>相当于</span><span>age&gt;=10 AND age&lt;=30<br>2</span><span>、列表运算符例：</span><span>country IN ('Germany','China')<br>3</span><span>、模式匹配符例：常用于模糊查找，它判断列值是否与指定的字符串格式相匹配。可用于</span><span>char</span><span>、</span><span>varchar</span><span>、</span><span>text</span><span>、</span><span>ntext</span><span>、</span><span>datetime</span><span>和</span><span>smalldatetime</span><span>等类型查询。</span><span><br></span><span>可使用以下通配字符：</span><span><br></span><span>　　百分号</span><span>%</span><span>：可匹配任意类型和长度的字符，如果是中文，请使用两个百分号即</span><span>%%</span><span>。</span><span><br></span><span>　　下划线</span><span>_</span><span>：匹配单个任意字符，它常用来限制表达式的字符长度。</span><span><br></span><span>　　方括号</span><span>[]</span><span>：指定一个字符、字符串或范围，要求所匹配对象为它们中的任一个。</span><span>[^]</span><span>：其取值也</span><span>[] </span><span>相同，但它要求所匹配对象为指定字符以外的任一个字符。</span><span><br></span><span>　　例如：</span><span><br></span><span>限制以</span><span>Publishing</span><span>结尾，使用</span><span>LIKE '%Publishing'<br></span><span>限制以</span><span>A</span><span>开头：</span><span>LIKE '[A]%'<br></span><span>限制以</span><span>A</span><span>开头外：</span><span>LIKE '[^A]%'<br>4</span><span>、空值判断符例</span><span>WHERE age IS NULL</span></p>
<p align=left><span>5</span><span>、逻辑运算符：优先级为</span><span>NOT</span><span>、</span><span>AND</span><span>、</span><span>OR<br><strong>(</strong></span><strong><span>四</span><span>)</span><span>查询结果排序</span></strong><span><br></span><span>　　</span><span><br></span><span>使用</span><span>ORDER BY</span><span>子句对查询返回的结果按一列或多列排序。</span><span>ORDER BY</span><span>子句的语法格式为：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span><br></span><span>　　</span><span>ORDER BY {column_name [ASC|DESC]} [,&#8230;n]</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><span>　　</span><span><br></span><span>其中</span><span>ASC</span><span>表示升序，为默认值，</span><span>DESC</span><span>为降序。</span><span>ORDER BY</span><span>不能按</span><span>ntext</span><span>、</span><span>text</span><span>和</span><span>image</span><span>数据类型进行排序。例如：</span></p>
<table cellSpacing=1 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td>
            <p align=left><span>　　</span><span><br></span><span>　　</span><span>SELECT *<br></span><span>　　</span><span>FROM usertable<br></span><span>　　</span><span>ORDER BY age desc,userid ASC</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=left><span><br></span><span>另外，可以根据表达式进行排序</span></p>
<p align=left><strong>&nbsp;<span>6.SQL TOP </span><span>用法</span></strong></p>
<p align=left><span>SELECT&nbsp;top&nbsp;100<span>&nbsp;&nbsp; </span>PERCENT&nbsp;LSBH</span></p>
<p align=left><span>FROM<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DSRJBXX</span></p>
<p align=left><span>查询全部</span><span>LSBH </span><span>的值</span></p>
<p align=left><span>TOP</span><span>子句</span></p>
<p align=left><span>从第一条或最后一条开始（利用</span><span>ORDER BY</span><span>条件子句），返回特定条数的数据。</span></p>
<p align=left><span>例如：</span></p>
<p align=left><span>当您想要知道在</span><span>2000</span><span>年，班上前</span><span>25</span><span>名的学生姓名数据时，您可以输入这样的语句：</span></p>
<p align=left><span>SELECT TOP 25 </span><span>学生姓名</span></p>
<p align=left><span>FORM </span><span>学生表格</span></p>
<p align=left><span>WHERE </span><span>毕业年份</span><span>=1994</span></p>
<p align=left><span>ORDER BY </span><span>毕业成绩平均分数</span><span> DESC</span><span>；</span></p>
<p align=left><span>如果您没有加上</span><span>ORDER BY </span><span>这行条件的话，您所得到的数据，将会随机的数据。此外，在</span><span>TOP</span><span>语句之后，除了可以加上数字以外，还可以利用保留字</span><span>PERCENT</span><span>来查询。</span></p>
<p align=left><span>例如：</span></p>
<p align=left><span>SELECT TOP 10 PERCENT</span><span>学生姓名</span></p>
<p align=left><span>FROM</span><span>学生表格</span></p>
<p align=left><span>WHERE</span><span>毕业年份</span><span>=1994</span></p>
<p align=left><span>ORDER BY</span><span>毕业成绩平均</span><span>DESC</span><span>；</span></p>
<p align=left><strong>&nbsp;</strong><span><strong>7.</strong><a href="http://www.cnitblog.com/taihang/archive/2006/06/09/11874.html"><strong><span>union</span><span><span>子句用法</span></span></strong></a> </span></p>
<p align=left><span>union</span><span>子句</span><span><br>union</span><span>操作符将两个查询结果合并为一个结果集。为连接查询合并两个表时：列的数日和顺序在查中必须一致；数据类型兼容</span><span><br></span><span>语法：</span><span><br>select &nbsp;</span><span>语句</span><span><br>union &nbsp; [ all ] <br>select &nbsp;</span><span>语句</span><span><br></span><span>注意：</span><span><br>1 .union</span><span>运算从最终结果集中删除重复记录，如想不删除重复记录使用</span><span>all</span><span>关键字</span><span><br>2 .</span><span>第一个</span><span>select</span><span>语句中不能用</span><span>order&nbsp;by</span><span>或</span><span>compute</span><span>子句，只能是最后一个</span><span>select</span><span>语名后用</span><span><br>&nbsp;</span><span>例：查询计算机系的学生式年龄不大于</span><span>19</span><span>岁的学习，按年龄倒排序</span><span><br>select &nbsp; * &nbsp; from &nbsp;department&nbsp; where &nbsp;dept = ' computer ' ;<br>union ;<br>select&nbsp; * &nbsp; from &nbsp;student&nbsp; where &nbsp;age &lt;= 19 <br>order &nbsp; by &nbsp;age&nbsp; desc <br></span><span>注：两表中字段一致，内容太丰富了。</span></p>
<img src ="http://www.cnitblog.com/malan11/aggbug/31139.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 13:00 <a href="http://www.cnitblog.com/malan11/articles/31139.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL优化</title><link>http://www.cnitblog.com/malan11/articles/31136.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 04:16:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31136.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31136.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31136.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31136.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31136.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: SQL&nbsp;优化&nbsp; 来自：CSDN&nbsp;（一）深入浅出理解索引结构&nbsp;&nbsp; 实际上，您可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引：聚集索引（clustered index，也称聚类索引、簇集索引）和非聚集索引（nonclustered index，也称非聚类索引、非簇集索引）。下面，我们举例来说明一下聚集索引和非聚集索引的...&nbsp;&nbsp;<a href='http://www.cnitblog.com/malan11/articles/31136.html'>阅读全文</a><img src ="http://www.cnitblog.com/malan11/aggbug/31136.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 12:16 <a href="http://www.cnitblog.com/malan11/articles/31136.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL Server存储过程编写和优化措施</title><link>http://www.cnitblog.com/malan11/articles/31134.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 03:49:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31134.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31134.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31134.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31134.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据库开发程序员，在数据库的开发过程中，经常会遇到复杂的业务逻辑和对数据库的操作，这个时候就会用SP来封装数据库操作。如果项目的SP较多，书写又没有一定的规范，将会影响以后的系统维护困难和大SP逻辑的难以理解，另外如果数据库的数据量大或者项目对SP的性能要求很，就会遇到优化的问题，否则速度有可能很慢，经过亲身经验，一个经过优化过的SP要比一个性能差的SP的效率甚至高几百倍。 　 <br>&nbsp;&nbsp;&nbsp; 内容： 　 <br>&nbsp;&nbsp;&nbsp; 1、开发人员如果用到其他库的Table或View，务必在当前库中建立View来实现跨库操作，最好不要直接使用&#8220;databse.dbo.table_name&#8221;，因为sp_depends不能显示出该SP所使用的跨库table或view，不方便校验。　　 <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 2、开发人员在提交SP前，必须已经使用set showplan on分析过查询计划，做过自身的查询优化检查。 　 </p>
<p>　3、高程序运行效率，优化应用程序，在SP编写过程中应该注意以下几点： 　　 </p>
<p>　　a)SQL的使用规范： </p>
<p>　　　i.　尽量避免大事务操作，慎用holdlock子句，提高系统并发能力。 </p>
<p>　　　ii.　尽量避免反复访问同一张或几张表，尤其是数据量较大的表，可以考虑先根据条件提取数据到临时表中，然后再做连接。 </p>
<p>　　　iii.　尽量避免使用游标，因为游标的效率较差，如果游标操作的数据超过1万行，那么就应该改写；如果使用了游标，就要尽量避免在游标循环中再进行表连接的操作。 </p>
<p>　　　iv.　注意where字句写法，必须考虑语句顺序，应该根据索引顺序、范围大小来确定条件子句的前后顺序，尽可能的让字段顺序与索引顺序相一致，范围从大到小。 </p>
<p>　　　v.　不要在where子句中的&#8220;=&#8221;左边进行函数、算术运算或其他表达式运算，否则系统将可能无法正确使用索引。 </p>
<p>　　　vi.　尽量使用exists代替select count(1)来判断是否存在记录，count函数只有在统计表中所有行数时使用，而且count(1)比count(*)更有效率。 </p>
<p>　　　vii.　尽量使用&#8220;&gt;=&#8221;，不要使用&#8220;&gt;&#8221;。 </p>
<p>　　　viii.　注意一些or子句和union子句之间的替换 </p>
<p>　　　ix.　注意表之间连接的数据类型，避免不同类型数据之间的连接。 </p>
<p>　　　x.　注意存储过程中参数和数据类型的关系。 </p>
<p>　　　xi.　注意insert、update操作的数据量，防止与其他应用冲突。如果数据量超过200个数据页面（400k），那么系统将会进行锁升级，页级锁会升级成表级锁。 　　 </p>
<p>　　b)索引的使用规范： </p>
<p>　　　i.　索引的创建要与应用结合考虑，建议大的OLTP表不要超过6个索引。 </p>
<p>　　　ii.　尽可能的使用索引字段作为查询条件，尤其是聚簇索引，必要时可以通过index index_name来强制指定索引 </p>
<p>　　　iii.　避免对大表查询时进行table scan，必要时考虑新建索引。 </p>
<p>　　　iv.　在使用索引字段作为条件时，如果该索引是联合索引，那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引，否则该索引将不会被使用。 </p>
<p>　　　v.　要注意索引的维护，周期性重建索引，重新编译存储过程。　　 </p>
<p>　　c)tempdb的使用规范： </p>
<p>　　　i.　尽量避免使用distinct、order by、group by、having、join、cumpute，因为这些语句会加重tempdb的负担。 </p>
<p>　　　ii.　避免频繁创建和删除临时表，减少系统表资源的消耗。 </p>
<p>　　　iii.　在新建临时表时，如果一次性插入数据量很大，那么可以使用select into代替create table，避免log，提高速度；如果数据量不大，为了缓和系统表的资源，建议先create table，然后insert。 </p>
<p>　　　iv.　如果临时表的数据量较大，需要建立索引，那么应该将创建临时表和建立索引的过程放在单独一个子存储过程中，这样才能保证系统能够很好的使用到该临时表的索引。 </p>
<p>　　　 v.　如果使用到了临时表，在存储过程的最后务必将所有的临时表显式删除，先truncate table，然后drop table，这样可以避免系统表的较长时间锁定。 </p>
<p>　　　 vi.　慎用大的临时表与其他大表的连接查询和修改，减低系统表负担，因为这种操作会在一条语句中多次使用tempdb的系统表。　　 <br>　　d)合理的算法使用： 　　 </p>
<p>　　根据上面已提到的SQL优化技术和ASE Tuning手册中的SQL优化内容,结合实际应用,采用多种算法进行比较,以获得消耗资源最少、效率最高的方法。具体可用ASE调优命令：set statistics io on, set statistics time on , set showplan on 等。 <br></p>
<img src ="http://www.cnitblog.com/malan11/aggbug/31134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 11:49 <a href="http://www.cnitblog.com/malan11/articles/31134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何提高SQL效率，作为一种思想方法，在编写SQL语句的时候，必须时刻注意。想不起来在哪里看到过这篇文章，这里先贴上去。</title><link>http://www.cnitblog.com/malan11/articles/31133.html</link><dc:creator>梦回菜园</dc:creator><author>梦回菜园</author><pubDate>Thu, 02 Aug 2007 03:46:00 GMT</pubDate><guid>http://www.cnitblog.com/malan11/articles/31133.html</guid><wfw:comment>http://www.cnitblog.com/malan11/comments/31133.html</wfw:comment><comments>http://www.cnitblog.com/malan11/articles/31133.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/malan11/comments/commentRss/31133.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/malan11/services/trackbacks/31133.html</trackback:ping><description><![CDATA[<span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><v:shapetype id=_x0000_t75 stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600">&nbsp;</v:shapetype></span><span>五种提高</span><span> SQL </span><span>性能的方法</span>
<p align=left><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有时，</span><span>为了让应用程序运行得更快，所做的全部工作就是在这里或那里做一些很小调整。但关键在于确定如何进行调整！迟早您会遇到这种情况：应用程序中的</span><span> SQL </span><span>查询不能按照您想要的方式进行响应。它要么不返回数据，要么耗费的时间长得出奇。如果它降低了报告或您的企业应用程序的速度，用户必须等待的时间过长，他们就会很不满意。就像您的父母不想听您解释为什么在深更半夜才回来一样，用户也不会听你解释为什么查询耗费这么长时间。（</span><span>&#8220;</span><span>对不起，妈妈，我使用了太多的</span><span> LEFT JOIN</span><span>。</span><span>&#8221;</span><span>）用户希望应用程序响应迅速，他们的报告能够在瞬间之内返回分析数据。就我自己而言，如果在</span><span> Web </span><span>上冲浪时某个页面要耗费十多秒才能加载（好吧，五秒更实际一些），我也会很不耐烦。</span><span>为了解决这些问题，重要的是找到问题的根源。那么，从哪里开始呢？根本原因通常在于数据库设计和访问它的查询。在本月的专栏中，我将讲述四项技术，这些技术可用于提高基于</span><span> SQL Server? </span><span>的应用程序的性能或改善其可伸缩性。我将仔细说明</span><span> LEFT JOIN</span><span>、</span><span>CROSS JOIN </span><span>的使用以及</span><span> IDENTITY </span><span>值的检索。请记住，根本没有神奇的解决方案。调整您的数据库及其查询需要占用时间、进行分析，还需要大量的测试。这些技术都已被证明行之有效，但对您的应用程序而言，可能其中一些技术比另一些技术更适用。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><strong><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">从</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> INSERT </span></strong><strong><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">返回</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> IDENTITY&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br></span></strong><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">&nbsp;&nbsp;&nbsp; 我决定从遇到许多问题的内容入手：如何在执行</span><span lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> SQL INSERT </span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">后检索</span><span lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> IDENTITY </span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">值。通常，问题不在于如何编写检索值的查询，而在于在哪里以及何时进行检索。在</span><span lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> SQL Server </span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">中，下面的语句可用于检索由最新在活动数据库连接上运行的</span><span lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> SQL </span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">语句所创建的</span><span lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> IDENTITY </span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">值：<br></span><span lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 140%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><o:p></o:p></span></p>
<p align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>SELECT @@IDENTITY</span></p>
<p align=left><span>这个</span><span> SQL </span><span>语句并不复杂，但需要记住的一点是：如果这个最新的</span><span> SQL </span><span>语句不是</span><span> INSERT</span><span>，或者您针对非</span><span> INSERT SQL </span><span>的其他连接运行了此</span><span> SQL</span><span>，则不会获得期望的值。您必须运行下列代码才能检索紧跟在</span><span> INSERT SQL </span><span>之后且位于同一连接上的</span><span> IDENTITY</span><span>，如下所示：</span></p>
<p align=left><span>INSERT INTO Products (ProductName) VALUES ('Chalk')</span></p>
<p align=left>&nbsp;<span>SELECT @@IDENTITY</span></p>
<p align=left><span>在一个连接上针对</span><span> Northwind </span><span>数据库运行这些查询将返回一个名称为</span><span> Chalk </span><span>的新产品的</span><span> IDENTITY </span><span>值。所以，在使用</span><span> ADO </span><span>的</span><span> Visual Basic? </span><span>应用程序中，可以运行以下语句：</span></p>
<p align=left><span>Set oRs = oCn.Execute("SET NOCOUNT ON;INSERT INTO Products _</span></p>
<p align=left><span>(ProductName) VALUES ('Chalk');SELECT @@IDENTITY")</span></p>
<p align=left>&nbsp;<span>lProductID = oRs(0)</span></p>
<p align=left><span>此代码告诉</span><span> SQL Server </span><span>不要返回查询的行计数，然后执行</span><span> INSERT </span><span>语句，并返回刚刚为这个新行创建的</span><span> IDENTITY </span><span>值。</span><span>SET NOCOUNT ON </span><span>语句表示返回的记录集有一行和一列，其中包含了这个新的</span><span> IDENTITY </span><span>值。如果没有此语句，则会首先返回一个空的记录集（因为</span><span> INSERT </span><span>语句不返回任何数据），然后会返回第二个记录集，第二个记录集中包含</span><span> IDENTITY </span><span>值。这可能有些令人困惑，尤其是因为您从来就没有希望过</span><span> INSERT </span><span>会返回记录集。之所以会发生此情况，是因为</span><span> SQL Server </span><span>看到了这个行计数（即一行受到影响）并将其解释为表示一个记录集。因此，真正的数据被推回到了第二个记录集。当然您可以使用</span><span> ADO </span><span>中的</span><span> NextRecordset </span><span>方法获取此第二个记录集，但如果总能够首先返回该记录集且只返回该记录集，则会更方便，也更有效率。</span></p>
<p align=left><span>此方法虽然有效，但需要在</span><span> SQL </span><span>语句中额外添加一些代码。获得相同结果的另一方法是在</span><span> INSERT </span><span>之前使用</span><span> SET NOCOUNT ON </span><span>语句，并将</span><span> SELECT @@IDENTITY </span><span>语句放在表中的</span><span> FOR INSERT </span><span>触发器中，如下面的代码片段所示。这样，任何进入该表的</span><span> INSERT </span><span>语句都将自动返回</span><span> IDENTITY </span><span>值。</span></p>
<p align=left><span>CREATE TRIGGER trProducts_Insert ON Products FOR INSERT AS </span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>SELECT @@IDENTITY </span></p>
<p align=left><span>GO</span></p>
<p align=left><span>触发器只在</span><span> Products </span><span>表上发生</span><span> INSERT </span><span>时启动，所以它总是会在成功</span><span> INSERT </span><span>之后返回一个</span><span> IDENTITY</span><span>。使用此技术，您可以始终以相同的方式在应用程序中检索</span><span> IDENTITY </span><span>值。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p align=left><strong><span>内嵌视图与临时表</span></strong><strong><span> </span></strong></p>
<p align=left><span>某些时候，查询需要将数据与其他一些可能只能通过执行</span><span> GROUP BY </span><span>然后执行标准查询才能收集的数据进行联接。例如，如果要查询最新五个定单的有关信息，您首先需要知道是哪些定单。这可以使用返回定单</span><span> ID </span><span>的</span><span> SQL </span><span>查询来检索。此数据就会存储在临时表（这是一个常用技术）中，然后与</span><span> Products </span><span>表进行联接，以返回这些定单售出的产品数量：</span></p>
<p align=left><span>CREATE TABLE #Temp1 (OrderID INT NOT NULL, _</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>OrderDate DATETIME NOT NULL)</span></p>
<p align=left>&nbsp;</p>
<p align=left><span>INSERT INTO #Temp1 (OrderID, OrderDate)</span></p>
<p align=left><span>SELECT<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>TOP 5 o.OrderID, o.OrderDate</span></p>
<p align=left><span>FROM Orders o ORDER BY o.OrderDate DESC</span></p>
<p align=left>&nbsp;</p>
<p align=left><span>SELECT<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>p.ProductName, SUM(od.Quantity) AS ProductQuantity</span></p>
<p align=left><span>FROM<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>#Temp1 t </span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>INNER JOIN [Order Details] od ON t.OrderID = od.OrderID</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>INNER JOIN Products p ON od.ProductID = p.ProductID </span></p>
<p align=left><span>GROUP BY p.ProductName</span></p>
<p align=left><span>ORDER BY p.ProductName</span></p>
<p align=left>&nbsp;</p>
<p align=left><span>DROP TABLE #Temp1</span></p>
<p align=left><span>这些</span><span> SQL </span><span>语句会创建一个临时表，将数据插入该表中，将其他数据与该表进行联接，然后除去该临时表。这会导致此查询进行大量</span><span> I/O </span><span>操作，因此，可以重新编写查询，使用内嵌视图取代临时表。内嵌视图只是一个可以联接到</span><span> FROM </span><span>子句中的查询。所以，您不用在</span><span> tempdb </span><span>中的临时表上耗费大量</span><span> I/O </span><span>和磁盘访问，而可以使用内嵌视图得到同样的结果：</span></p>
<p align=left><span>SELECT p.ProductName, </span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>SUM(od.Quantity) AS ProductQuantity</span></p>
<p align=left><span>FROM<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>(</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>SELECT TOP 5 o.OrderID, o.OrderDate</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>FROM<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>Orders o </span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>ORDER BY o.OrderDate DESC</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>) t </span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>INNER JOIN [Order Details] od ON t.OrderID = od.OrderID</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>INNER JOIN Products p ON od.ProductID = p.ProductID </span></p>
<p align=left><span>GROUP BY</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>p.ProductName</span></p>
<p align=left><span>ORDER BY</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>p.ProductName</span></p>
<p align=left><span>此查询不仅比前面的查询效率更高，而且长度更短。临时表会消耗大量资源。如果只需要将数据联接到其他查询，则可以试试使用内嵌视图，以节省资源。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p align=left><strong><span>避免</span></strong><strong><span> LEFT JOIN </span></strong><strong><span>和</span></strong><strong><span> NULL </span></strong></p>
<p align=left><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然，有很多时候您需要执行</span><span> LEFT JOIN </span><span>和使用</span><span> NULL </span><span>值。但是，它们并不适用于所有情况。改变</span><span> SQL </span><span>查询的构建方式可能会产生将一个花几分钟运行的报告缩短到只花几秒钟这样的天壤之别的效果。有时，必须在查询中调整数据的形态，使之适应应用程序所要求的显示方式。虽然</span><span> TABLE </span><span>数据类型会减少大量占用资源的情况，但在查询中还有许多区域可以进行优化。</span><span>SQL </span><span>的一个有价值的常用功能是</span><span> LEFT JOIN</span><span>。它可以用于检索第一个表中的所有行、第二个表中所有匹配的行、以及第二个表中与第一个表不匹配的所有行。例如，如果希望返回每个客户及其定单，使用</span><span> LEFT JOIN </span><span>则可以显示有定单和没有定单的客户。</span></p>
<p align=left><span>此工具可能会被过度使用。</span><span>LEFT JOIN </span><span>消耗的资源非常之多，因为它们包含与</span><span> NULL</span><span>（不存在）数据匹配的数据。在某些情况下，这是不可避免的，但是代价可能非常高。</span><span>LEFT JOIN </span><span>比</span><span> INNER JOIN </span><span>消耗资源更多，所以如果您可以重新编写查询以使得该查询不使用任何</span><span> LEFT JOIN</span><span>，则会得到非常可观的回报。</span><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><v:shapetype id=_x0000_t75 stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600">&nbsp;<span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><v:shapetype id=_x0000_t75 stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p align=left><span>加快使用</span><span> LEFT JOIN </span><span>的查询速度的一项技术涉及创建一个</span><span> TABLE </span><span>数据类型，插入第一个表（</span><span>LEFT JOIN </span><span>左侧的表）中的所有行，然后使用第二个表中的值更新</span><span> TABLE </span><span>数据类型。此技术是一个两步的过程，但与标准的</span><span> LEFT JOIN </span><span>相比，可以节省大量时间。一个很好的规则是尝试各种不同的技术并记录每种技术所需的时间，直到获得用于您的应用程序的执行性能最佳的查询。</span></p>
<p align=left><span>测试查询的速度时，有必要多次运行此查询，然后取一个平均值。因为查询（或存储过程）可能会存储在</span><span> SQL Server </span><span>内存中的过程缓存中，因此第一次尝试耗费的时间好像稍长一些，而所有后续尝试耗费的时间都较短。另外，运行您的查询时，可能正在针对相同的表运行其他查询。当其他查询锁定和解锁这些表时，可能会导致您的查询要排队等待。例如，如果您进行查询时某人正在更新此表中的数据，则在更新提交时您的查询可能需要耗费更长时间来执行。</span></p>
<p align=left><span>避免使用</span><span> LEFT JOIN </span><span>时速度降低的最简单方法是尽可能多地围绕它们设计数据库。例如，假设某一产品可能具有类别也可能没有类别。如果</span><span> Products </span><span>表存储了其类别的</span><span> ID</span><span>，而没有用于某个特定产品的类别，则您可以在字段中存储</span><span> NULL </span><span>值。然后您必须执行</span><span> LEFT JOIN </span><span>来获取所有产品及其类别。您可以创建一个值为</span><span>&#8220;No Category&#8221;</span><span>的类别，从而指定外键关系不允许</span><span> NULL </span><span>值。通过执行上述操作，现在您就可以使用</span><span> INNER JOIN </span><span>检索所有产品及其类别了。虽然这看起来好像是一个带有多余数据的变通方法，但可能是一个很有价值的技术，因为它可以消除</span><span> SQL </span><span>批处理语句中消耗资源较多的</span><span> LEFT JOIN</span><span>。在数据库中全部使用此概念可以为您节省大量的处理时间。请记住，对于您的用户而言，即使几秒钟的时间也非常重要，因为当您有许多用户正在访问同一个联机数据库应用程序时，这几秒钟实际上的意义会非常重大。</span><span> </span></p>
<p align=left><strong><span>灵活使用笛卡尔乘积</span></strong><strong><span> </span></strong></p>
<p align=left><span>对于此技巧，我将进行非常详细的介绍，并提倡在某些情况下使用笛卡尔乘积。出于某些原因，笛卡尔乘积</span><span> (CROSS JOIN) </span><span>遭到了很多谴责，开发人员通常会被警告根本就不要使用它们。在许多情况下，它们消耗的资源太多，从而无法高效使用。但是像</span><span> SQL </span><span>中的任何工具一样，如果正确使用，它们也会很有价值。例如，如果您想运行一个返回每月数据（即使某一特定月份客户没有定单也要返回）的查询，您就可以很方便地使用笛卡尔乘积。</span><span><a href="http://www.microsoft.com/china/MSDN/library/data/sqlserver/art/figures3.html" target=_blank><span> </span><span><span>图</span></span><span> 2 </span></a></span><span>中的</span><span> SQL </span><span>就执行了上述操作。</span></p>
<p align=left><span>虽然这看起来好像没什么神奇的，但是请考虑一下，如果您从客户到定单（这些定单按月份进行分组并对销售额进行小计）进行了标准的</span><span> INNER JOIN</span><span>，则只会获得客户有定单的月份。因此，对于客户未订购任何产品的月份，您不会获得</span><span> 0 </span><span>值。如果您想为每个客户都绘制一个图，以显示每个月和该月销售额，则可能希望此图包括月销售额为</span><span> 0 </span><span>的月份，以便直观标识出这些月份。如果使用</span><span> <span><a href="http://www.microsoft.com/china/MSDN/library/data/sqlserver/art/figures3.html" target=_blank><span><span>图</span></span><span> 2 </span></a></span></span><span>中的</span><span> SQL</span><span>，数据则会跳过销售额为</span><span> 0 </span><span>美元的月份，因为在定单表中对于零销售额不会包含任何行（假设您只存储发生的事件）。</span><span><a href="http://www.microsoft.com/china/MSDN/library/data/sqlserver/art/figures3.html" target=_blank><span><span>图</span></span><span> 3 </span></a></span><span>中的代码虽然较长，但是可以达到获取所有销售数据（甚至包括没有销售额的月份）的目标。首先，它会提取去年所有月份的列表，然后将它们放入第一个</span><span> TABLE </span><span>数据类型表</span><span> (@tblMonths) </span><span>中。下一步，此代码会获取在该时间段内有销售额的所有客户公司的名称列表，然后将它们放入另一个</span><span> TABLE </span><span>数据类型表</span><span> (@tblCus-tomers) </span><span>中。这两个表存储了创建结果集所必需的所有基本数据，但实际销售数量除外。</span><span> </span><span>第一个表中列出了所有月份（</span><span>12 </span><span>行），第二个表中列出了这个时间段内有销售额的所有客户（对于我是</span><span> 81 </span><span>个）。并非每个客户在过去</span><span> 12 </span><span>个月中的每个月都购买了产品，所以，执行</span><span> INNER JOIN </span><span>或</span><span> LEFT JOIN </span><span>不会返回每个月的每个客户。这些操作只会返回购买产品的客户和月份。</span></p>
<p align=left><span>笛卡尔乘积则可以返回所有月份的所有客户。笛卡尔乘积基本上是将第一个表与第二个表相乘，生成一个行集合，其中包含第一个表中的行数与第二个表中的行数相乘的结果。因此，笛卡尔乘积会向表</span><span> @tblFinal </span><span>返回</span><span> 972 </span><span>行。最后的步骤是使用此日期范围内每个客户的月销售额总计更新</span><span> @tblFinal </span><span>表，以及选择最终的行集。</span></p>
<p align=left><span>如果由于笛卡尔乘积占用的资源可能会很多，而不需要真正的笛卡尔乘积，则可以谨慎地使用</span><span> CROSS JOIN</span><span>。例如，如果对产品和类别执行了</span><span> CROSS JOIN</span><span>，然后使用</span><span> WHERE </span><span>子句、</span><span>DISTINCT </span><span>或</span><span> GROUP BY </span><span>来筛选出大多数行，那么使用</span><span> INNER JOIN </span><span>会获得同样的结果，而且效率高得多。如果需要为所有的可能性都返回数据（例如在您希望使用每月销售日期填充一个图表时），则笛卡尔乘积可能会非常有帮助。但是，您不应该将它们用于其他用途，因为在大多数方案中</span><span> INNER JOIN </span><span>的效率要高得多。</span></p>
<p align=left><strong><span>拾遗补零</span></strong><strong><span> </span></strong></p>
<p align=left><span>这里介绍其他一些可帮助提高</span><span> SQL </span><span>查询效率的常用技术。假设您将按区域对所有销售人员进行分组并将他们的销售额进行小计，但是您只想要那些数据库中标记为处于活动状态的销售人员。您可以按区域对销售人员分组，并使用</span><span> HAVING </span><span>子句消除那些未处于活动状态的销售人员，也可以在</span><span> WHERE </span><span>子句中执行此操作。在</span><span> WHERE </span><span>子句中执行此操作会减少需要分组的行数，所以比在</span><span> HAVING </span><span>子句中执行此操作效率更高。</span><span>HAVING </span><span>子句中基于行的条件的筛选会强制查询对那些在</span><span> WHERE </span><span>子句中会被去除的数据进行分组。另一个提高效率的技巧是使用</span><span> DISTINCT </span><span>关键字查找数据行的单独报表，来代替使用</span><span> GROUP BY </span><span>子句。在这种情况下，使用</span><span> DISTINCT </span><span>关键字的</span><span> SQL </span><span>效率更高。请在需要计算聚合函数（</span><span>SUM</span><span>、</span><span>COUNT</span><span>、</span><span>MAX </span><span>等）的情况下再使用</span><span> GROUP BY</span><span>。另外，如果您的查询总是自己返回一个唯一的行，则不要使用</span><span> DISTINCT </span><span>关键字。在这种情况下，</span><span>DISTINCT </span><span>关键字只会增加系统开销。您已经看到了，有大量技术都可用于优化查询和实现特定的业务规则，技巧就是进行一些尝试，然后比较它们的性能。最重要的是要测试、测试、再测试。</span></p>
<p align=left><br>&nbsp;&nbsp;&nbsp; </v:shapetype></span></v:shapetype></span></span></span></span></p>
<img src ="http://www.cnitblog.com/malan11/aggbug/31133.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/malan11/" target="_blank">梦回菜园</a> 2007-08-02 11:46 <a href="http://www.cnitblog.com/malan11/articles/31133.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>