<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>听雪堂 &#187; 工作备忘</title>
	<atom:link href="http://snow.snowrain.org/category/working-notes/feed/" rel="self" type="application/rss+xml" />
	<link>http://snow.snowrain.org</link>
	<description></description>
	<lastBuildDate>Fri, 27 Jan 2012 15:11:17 +0000</lastBuildDate>
	<language>zh-cn</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>北京出差</title>
		<link>http://snow.snowrain.org/2010/10/30/beijing-trip/</link>
		<comments>http://snow.snowrain.org/2010/10/30/beijing-trip/#comments</comments>
		<pubDate>Sat, 30 Oct 2010 09:12:01 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[照相本子]]></category>
		<category><![CDATA[生活点滴]]></category>
		<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/2010/10/30/beijing-trip/</guid>
		<description><![CDATA[其实是开会, 上个月老板问我说要不要去北京听听vmware布道, 我想了想, vmworld trip被取消, 国内的vforum凑合听听吧, 再说很久也没去北京了, 顺道去看看想必也不错. 结果当时计划的时候忘记了上周要去塞班的事情, 导致我的行程非常赶 -- 刚从塞班回来就直奔北京而去. 住在离北京站不远的东单, 政协会议中心. 下车后就觉得帝都的空气实在太干净了, 天空也很蓝, 比不上塞班深邃的蓝色, 但至少不像南京那样是灰色, 还有秋日里的阳光, 晒的人懒懒的, 走在满是银杏树干净的大街上, 我突然对北京的印象180度大转. 然后就是vmware的大会, 用台北同事的话来讲, 这种会议叫做&#34;大拜拜&#34;, 上午到会场checkin之后拿到一张卡片, 工作人员说要在会场里到处盖戳, 盖满了之后能换个小礼物... 沃勒个去... 40多个戳, 弄的跟sb会似的, 太恶俗了! 整个会场里都是拿着卡片找人盖戳的... 你们IT民工有点出息好不好. 在会场里转了转, 然后就说主会场的大会开始了. 听到第三个人上台, 我跟两个同事坐不住了 -- 讲的东西太泛泛. 还不如出去跟vmware以及厂商的技术人员聊天来的痛快. 于是我们就先跑到vmware的展区, 找了两个技术人员问了些关于vaai的一些问题, 然后又下楼去看EMC各个子公司提供的方案, EMC对行业的把握还是很到位的, 这几年接连收购一系列的公司, 收购之后几乎就都变成了行业热点. vmware, rsa, data domain…这些兄弟公司相互之间互相火力支援, 一步一步占领市场... 扯远了. 反正又在楼下的EMC展区跟各个工作人员以及解决方案厂商聊了不少. 趁着这个时候没什么人, [...]]]></description>
			<content:encoded><![CDATA[<p>其实是开会, 上个月老板问我说要不要去北京听听vmware布道, 我想了想, vmworld trip被取消, 国内的vforum凑合听听吧, 再说很久也没去北京了, 顺道去看看想必也不错. 结果当时计划的时候忘记了上周要去塞班的事情, 导致我的行程非常赶 -- 刚从塞班回来就直奔北京而去.</p>
<p>住在离北京站不远的东单, 政协会议中心. 下车后就觉得帝都的空气实在太干净了, 天空也很蓝, 比不上塞班深邃的蓝色, 但至少不像南京那样是灰色, 还有秋日里的阳光, 晒的人懒懒的, 走在满是银杏树干净的大街上, 我突然对北京的印象180度大转.</p>
<p>然后就是vmware的大会, 用台北同事的话来讲, 这种会议叫做&quot;大拜拜&quot;, 上午到会场checkin之后拿到一张卡片, 工作人员说要在会场里到处盖戳, 盖满了之后能换个小礼物... 沃勒个去... 40多个戳, 弄的跟sb会似的, 太恶俗了! 整个会场里都是拿着卡片找人盖戳的... 你们IT民工有点出息好不好. 在会场里转了转, 然后就说主会场的大会开始了. 听到第三个人上台, 我跟两个同事坐不住了 -- 讲的东西太泛泛. 还不如出去跟vmware以及厂商的技术人员聊天来的痛快. 于是我们就先跑到vmware的展区, 找了两个技术人员问了些关于vaai的一些问题, 然后又下楼去看EMC各个子公司提供的方案, EMC对行业的把握还是很到位的, 这几年接连收购一系列的公司, 收购之后几乎就都变成了行业热点. vmware, rsa, data domain…这些兄弟公司相互之间互相火力支援, 一步一步占领市场... 扯远了. 反正又在楼下的EMC展区跟各个工作人员以及解决方案厂商聊了不少. 趁着这个时候没什么人, 我很猥琐地把戳给盖满了... orz 不过总得来跟技术人员聊天还颇有收获. 如果没有这些聊天, 可能我得回头自己读上好几天的资料.</p>
<p>中午的会场午餐券是要用调查问卷来换取的, 我们几个没填, 跑外头吃了. 吃完把大会发的资料啥的放回酒店 -- 太重了, 在酒店把资料过了一遍, 基本上都可以扔掉, 太浪费纸张了.</p>
<p>在酒店小睡片刻, 大约1点15分左右的样子从酒店出发去会场参加下午的会, 结果到了会场, 原定一点开始的分会场会议人还都挤在门外... 我挑了看起来跟存储虚拟化有关的分会场. 其他人也各自选自己的topic去听. 整个下午的分会场session中, 我觉得只有compellent的还有点份量, 其他的一般般. 所有的议程走完之后是抽奖时刻, 我居然很幸运地被抽中成为场内唯一的IPAD赢家...</p>
<p><a href="http://www.flickr.com/photos/snowprint/5125767966/"><img border="0" alt="ÖÐ½±Ö®ÕæÏà - 16G wifi°æ" src="http://farm2.static.flickr.com/1233/5125767966_c7a0d3d56f.jpg" width="500" height="333" /></a></p>
<p>晚上承蒙Jackie伉俪的关照, 喊了<a href="http://wang.yuxuan.org"  class="alinks_links" onclick="return alinks_click(this);" title="fishy"  style="padding-right: 13px; background: url(http://snow.snowrain.org/wp-content/plugins/alinks/images/external.png) center right no-repeat;" rel="external">鱼总</a>(fishy)和Eric一起吃饭. 在建国门附近一家叫My Dining(春平之家)的饭店. 酒足饭饱之后Eric开车拉着五个人去鱼总隐居之处参观, 见到了传说中的<a href="http://wang.yuxuan.org/fuwa.php" target="_blank">福大爷</a>. 然后饶有兴致的玩了两轮Modern Art桌游. 很有趣的桌游, 可惜我是个色弱... 本来刚开始还能认清颜色的, 到后来老眼昏花, 其中两个颜色有点分不清 @_@ btw, 这个游戏还挺有意思的, 准备回头也买一套~</p>
<blockquote><p><img src="http://pic.snowrain.org/webpic/20101030-Beijing/IMG_20101029_213421.jpg" /></p>
<p>惊恐的福娃</p>
</blockquote>
<p>今天早上起来, 跟同事在楼下吃了回东来顺, 然后回酒店checkout, 坐地铁到南站沿线附近逛逛, 有点后悔这次出差没有带相机, 否则可以去鱼总学校拍银杏的. 我对逛街没有兴趣, 于是找了一家咖啡店坐下来上网, 这家店还挺有味道的. 店老板也非常非常nice. 嗯,值得推荐. 叫做<a href="http://www.thebeijinger.com/directory/Colores-Cafe-and-Bar" target="_blank">彩咖啡</a>.</p>
<blockquote><p><img src="http://pic.snowrain.org/webpic/20101030-Beijing/IMG_20101030_152311.jpg" /></p>
<p>咖啡店内部</p>
<p><img src="http://pic.snowrain.org/webpic/20101030-Beijing/IMG_20101030_152324.jpg" /></p>
<p>我坐在临窗的座位, 外面是停滞不前的车流</p>
</blockquote>
<p>喝了两杯咖啡, 然后就顺便记了这篇blog.</p>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2010/10/30/beijing-trip/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>vSphere PowerCLI的折腾备忘</title>
		<link>http://snow.snowrain.org/2009/08/19/vsphere-powercli-programming-tips/</link>
		<comments>http://snow.snowrain.org/2009/08/19/vsphere-powercli-programming-tips/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 21:12:05 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/?p=368</guid>
		<description><![CDATA[VMWARE提供的SDK文档实在太难懂. 搞不懂为啥不直接给web service的引用文档. 对着提供的对象属性一边猜一边尝试, 进展颇微. 茶歇的时候翻了翻vmware提供的powershell toolkit, 感觉这个东西很有趣, 想了想部分功能用这东西做workaround不错, 以前也看过一些关于powershell的文档, 据说powershell里面到处都是对象, 用起来会比较顺手, 而且集成到.net程序里也方便, 但是一直对这东西是处于"知道"的阶段, 还从来没用过,  试试看吧, 事先想到了这样的缺点 -- 有可能性能上会产生瓶颈. 实际上优点也是显而易见的 -- 省掉了很多自己封装功能的工作量... 花了点小时间一边吃东西一边上网查解决办法, 把一个ugly的helloworld调通了, 记录几点过程中有用的tips, 都是网上找来的办法, 写下来再还给网络: 1. 先装powershell, 再装VMware提供的vSphere PowerCLI, 运行的时候会有这样的错误: File C:\Program Files\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-VIToolkitEnvironment.ps1 cannot be load ed because the execution of scripts is disabled on this system. Please see "get-help about_signing" for [...]]]></description>
			<content:encoded><![CDATA[<p>VMWARE提供的SDK文档实在太难懂. 搞不懂为啥不直接给web service的引用文档. 对着提供的对象属性一边猜一边尝试, 进展颇微.</p>
<p>茶歇的时候翻了翻vmware提供的powershell toolkit, 感觉这个东西很有趣, 想了想部分功能用这东西做workaround不错, 以前也看过一些关于powershell的文档, 据说powershell里面到处都是对象, 用起来会比较顺手, 而且集成到.net程序里也方便, 但是一直对这东西是处于"知道"的阶段, 还从来没用过,  试试看吧, 事先想到了这样的缺点 -- 有可能性能上会产生瓶颈. 实际上优点也是显而易见的 -- 省掉了很多自己封装功能的工作量...</p>
<p>花了点小时间一边吃东西一边上网查解决办法, 把一个ugly的helloworld调通了, 记录几点过程中有用的tips, 都是网上找来的办法, 写下来再还给网络:</p>
<p><strong>1. </strong>先装powershell, 再装VMware提供的vSphere PowerCLI, 运行的时候会有这样的错误:</p>
<blockquote><p><span style="font-size: x-small;">File C:\Program Files\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-VIToolkitEnvironment.ps1 cannot be load<br />
ed because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details.<br />
At line:1 char:2<br />
+ . &lt;&lt;&lt;&lt;  "C:\Program Files\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-VIToolkitEnvironment.ps1"<br />
PS C:\Program Files\VMware\Infrastructure\vSphere PowerCLI&gt;</span></p></blockquote>
<p>通过在powershell里运行"set-executionpolicy unrestricted"解决. -- <a href="http://www.abbottinternet.co.uk/2009/07/getting-started-with-powershell-and-vmware/" target="_blank">VIA</a></p>
<p><strong>2. </strong>我是在xp系统上安装的powershell 1.0, 在调用powershell的时候, 遇到了System.Management.Automation命名空间找不到的问题. 理论上这个 System.Management.Automation.dll 文件应该存在于:<br />
"C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\"<br />
目录下. 可惜没找到. 后来在<br />
"c:\WINDOWS\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\"<br />
目录下把这个dll直接copy出来, 引用后命名空间可用了.  -- <a href="http://www.eggheadcafe.com/conversation.aspx?messageid=31172431&amp;threadid=31172429" target="_blank">VIA</a></p>
<p><strong>3. </strong>写个小程序通过powershell打开VIServer连接的时候, 又遇上了一个问题:</p>
<blockquote><p><span style="font-size: xx-small;">The term 'connect-VIServer' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.</span></p></blockquote>
<p>这是因为没有加载VI snapin. 在脚本头加上这样一行就ok了:</p>
<blockquote><p>Add-PSSnapIn VMware.VimAutomation.Core -- <a href="http://powergui.org/thread.jspa?messageID=25148" target="_blank">VIA</a></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2009/08/19/vsphere-powercli-programming-tips/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>snapshot?废柴?</title>
		<link>http://snow.snowrain.org/2009/05/12/useless-sql-server-2005-snapshot/</link>
		<comments>http://snow.snowrain.org/2009/05/12/useless-sql-server-2005-snapshot/#comments</comments>
		<pubDate>Tue, 12 May 2009 11:48:24 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[软件网络]]></category>
		<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/?p=315</guid>
		<description><![CDATA[SQL Server 2005的snapshot创建起来几乎不花时间--源数据库发生改变的时候才实际写入. 但是看了一下, 好像除了像VMware的snapshot一样, 用来做做试验, 恢复原始环境, 几乎没啥作用: 快照文件无法修改, 一旦创建就以当前时间戳为准, 硬邦邦地躺在那里, 这个看起来不是缺点, 不过我觉得灵活性上还是差了点; 快照文件不能被删除,备份,还原 -- 那么就意味着巨大的风险, 当服务器发生故障, 无从转移,snapshot全挂; 不支持全文索引 -- 不过貌似SQL Server的全文索引用得也越来越少了; 快照建立后, 基础数据库无法删除, 分离或还原. 也不知道我的理解是否正确,数据安全无从保障,介绍中说的用来生成历史数据报表的用法就很扯淡了.]]></description>
			<content:encoded><![CDATA[<p>SQL Server 2005的snapshot创建起来几乎不花时间--源数据库发生改变的时候才实际写入. 但是看了一下, 好像除了像VMware的snapshot一样, 用来做做试验, 恢复原始环境, 几乎没啥作用:</p>
<ol>
<li>快照文件无法修改, 一旦创建就以当前时间戳为准, 硬邦邦地躺在那里, 这个看起来不是缺点, 不过我觉得灵活性上还是差了点;</li>
<li>快照文件不能被删除,备份,还原 -- 那么就意味着巨大的风险, 当服务器发生故障, 无从转移,snapshot全挂;</li>
<li>不支持全文索引 -- 不过貌似SQL Server的全文索引用得也越来越少了;</li>
<li>快照建立后, 基础数据库无法删除, 分离或还原.</li>
</ol>
<p>也不知道我的理解是否正确,数据安全无从保障,介绍中说的用来生成历史数据报表的用法就很扯淡了.</p>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2009/05/12/useless-sql-server-2005-snapshot/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>一个DTS包的数据库连接错误</title>
		<link>http://snow.snowrain.org/2009/04/17/a-connection-issue-happened-inside-a-dts-package/</link>
		<comments>http://snow.snowrain.org/2009/04/17/a-connection-issue-happened-inside-a-dts-package/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 13:26:43 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/2009/04/17/a-connection-issue-happened-inside-a-dts-package/</guid>
		<description><![CDATA[DTS的错误有时候调起来很费事. 特别是碰一下就要跑两个小时的DTS包很让人没耐心. 晚上就遇到这么一个情况, 从远端数据库迁移数据失败, 看了一下, 问题很简单, 数据库之间建立的连接失败. [DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied. 刚刚看到这个报错的时候, 还以为是帐户设置问题, 但前面的DBNETLIB还是让人觉得有点丈二. 查了半天, 没有得到确切的答案, 非常有可能的原因是远端数据库起了IPSec, 解决的workaround就是hardcode DB连接(IP,port), 好吧, 憋了一口气, 钻到那个不定期失去响应几秒的remote console, 把7,8个连接从头到尾都过了一遍. 执行, 看到屏幕上的窗口回显, 来回舞弄了大概500W+笔数据记录, 最后说successful, 看了一下时间, 嗯, 历时2小时. 顺便记一下, 最近还掺和(involve)了EMEA的一个所谓的global project, 我主要的作用就是在里头打打酱油, 这种不粘锅的感觉真好. 哦吔.]]></description>
			<content:encoded><![CDATA[<p>DTS的错误有时候调起来很费事. 特别是碰一下就要跑两个小时的DTS包很让人没耐心.</p>
<p>晚上就遇到这么一个情况, 从远端数据库迁移数据失败, 看了一下, 问题很简单, 数据库之间建立的连接失败.</p>
<blockquote><p>[DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied. </p>
</blockquote>
<p>刚刚看到这个报错的时候, 还以为是帐户设置问题, 但前面的DBNETLIB还是让人觉得有点丈二. 查了半天, 没有得到确切的答案, 非常有可能的原因是远端数据库起了IPSec, 解决的workaround就是hardcode DB连接(IP,port), 好吧, 憋了一口气, 钻到那个不定期失去响应几秒的remote console, 把7,8个连接从头到尾都过了一遍. 执行, 看到屏幕上的窗口回显, 来回舞弄了大概500W+笔数据记录, 最后说successful, 看了一下时间, 嗯, 历时2小时.</p>
<p>顺便记一下, 最近还掺和(involve)了EMEA的一个所谓的global project, 我主要的作用就是在里头打打酱油, 这种不粘锅的感觉真好. 哦吔.</p>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2009/04/17/a-connection-issue-happened-inside-a-dts-package/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>修改数据库COLLATION时候的锁</title>
		<link>http://snow.snowrain.org/2009/04/15/exclusively-lock-on-database-collation-alteration/</link>
		<comments>http://snow.snowrain.org/2009/04/15/exclusively-lock-on-database-collation-alteration/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 07:19:28 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/2009/04/15/exclusively-lock-on-database-collation-alteration/</guid>
		<description><![CDATA[QUEST的LITESPEED出问题了, 完整备份一切正常, 但是差异备份和事务备份总报错. 找原因的时候顺便发现LiteSpeed连数据库的logshipping有问题. 尽管这可能不是导致问题的根本原因, 但还是解掉比较好, 联系QUEST的Support, 他们能给出的建议是重新把instance配置一下. 配置走到最后一步果然有问题, LiteSpeed没有用数据库默认的COLLATE, 这样导致在配置的最后一步发生了冲突没法进行下去. 然后QUEST回信说试试看修改一下数据库的COLLATION, 使之与几个系统数据库的COLLATION一致. 虽然觉得有点不靠谱, 这样做实际上已经创建表的排序规则是无法改变的. 但软件是人家做的, 试试看吧. 直接去alter database, 返回一个排它锁错误: Server: Msg 5030, Level 16, State 2, Line 1 The database could not be exclusively locked to perform the operation. 嗯, 烦不了了, 先改成单用户模式吧: ALTER DATABASE db_database SET SINGLE_USER WITH ROLLBACK IMMEDIATE 再alter, 这下ok了. 之后再改回来: ALTER [...]]]></description>
			<content:encoded><![CDATA[<p>QUEST的LITESPEED出问题了, 完整备份一切正常, 但是差异备份和事务备份总报错. 找原因的时候顺便发现LiteSpeed连数据库的logshipping有问题. 尽管这可能不是导致问题的根本原因, 但还是解掉比较好, 联系QUEST的Support, 他们能给出的建议是重新把instance配置一下.</p>
<p>配置走到最后一步果然有问题, LiteSpeed没有用数据库默认的COLLATE, 这样导致在配置的最后一步发生了冲突没法进行下去. 然后QUEST回信说试试看修改一下数据库的COLLATION, 使之与几个系统数据库的COLLATION一致. 虽然觉得有点不靠谱, 这样做实际上已经创建表的排序规则是无法改变的. 但软件是人家做的, 试试看吧.</p>
<p>直接去alter database, 返回一个排它锁错误:</p>
<blockquote><p>Server: Msg 5030, Level 16, State 2, Line 1     <br />The database could not be exclusively locked to perform the operation.</p>
</blockquote>
<p>嗯, 烦不了了, 先改成单用户模式吧:</p>
<p>
<pre name="code" class="sql">
ALTER DATABASE db_database SET SINGLE_USER WITH ROLLBACK IMMEDIATE</pre>
</p>
<p>再alter, 这下ok了.</p>
<p>之后再改回来:</p>
<p>
<pre name="code" class="sql">ALTER DATABASE db_database SET MULTI_USER</pre>
</p>
<p>嗯, LiteSpeed也很怪. 这样糊弄一下, 居然就能继续配置下去了...</p>
<p>最后, 顺便记一个查数据库属性的存储过程: <a href="http://msdn.microsoft.com/en-us/library/ms186823.aspx" target="_blank">DATABASEPROPERTYEX</a></p>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2009/04/15/exclusively-lock-on-database-collation-alteration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server脚本--列出所有数据库文件,父子节点关系约束</title>
		<link>http://snow.snowrain.org/2009/03/20/sql-statements-list-data-files-and-enforcing-parent-child-relationship/</link>
		<comments>http://snow.snowrain.org/2009/03/20/sql-statements-list-data-files-and-enforcing-parent-child-relationship/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 16:43:38 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/2009/03/20/sql-statements-list-data-files-and-enforcing-parent-child-relationship/</guid>
		<description><![CDATA[最近查了一些别人写的数据库脚本.印象比较深的是这么两个: 1. 列出所有数据库文件. 这是因为要做几个数据库的迁移, 迁移之前需要对所有的物理文件以及逻辑文件做一个整理. Windows 的SQL Server本身提供了一个系统存储过程 - sp_spaceused, 不过这个返回的结果集比较有限.常用的方法还是去系统表sysfiles中找. 嗯, 按照往常的做法, 一个循环, 把全部的数据库列一下, 需要的东西就有了. 有意思的是, 今天在MSSQLTips网站上看到了这段: DECLARE @DBInfo TABLE ( ServerName VARCHAR(100), DatabaseName VARCHAR(100), FileSizeMB INT, LogicalFileName sysname, PhysicalFileName NVARCHAR(520), Status sysname, Updateability sysname, RecoveryMode sysname, FreeSpaceMB INT, FreeSpacePct VARCHAR(7), FreeSpacePages INT, PollDate datetime) DECLARE @command VARCHAR(5000) SELECT @command = 'Use [' + [...]]]></description>
			<content:encoded><![CDATA[<p>最近查了一些别人写的数据库脚本.印象比较深的是这么两个:</p>
<p>1. 列出所有数据库文件.</p>
<p>这是因为要做几个数据库的迁移, 迁移之前需要对所有的物理文件以及逻辑文件做一个整理. Windows 的SQL Server本身提供了一个系统存储过程 - <a href="http://msdn.microsoft.com/en-us/library/ms188776.aspx" target="_blank">sp_spaceused</a>, 不过这个返回的结果集比较有限.常用的方法还是去系统表sysfiles中找. 嗯, 按照往常的做法, 一个循环, 把全部的数据库列一下, 需要的东西就有了. 有意思的是, 今天在<a href="http://www.mssqltips.com/tip.asp?tip=1426" target="_blank">MSSQLTips</a>网站上看到了这段:</p>
<p>
<pre class="sql" name="code">DECLARE @DBInfo TABLE
( ServerName VARCHAR(100),
DatabaseName VARCHAR(100),
FileSizeMB INT,
LogicalFileName sysname,
PhysicalFileName NVARCHAR(520),
Status sysname,
Updateability sysname,
RecoveryMode sysname,
FreeSpaceMB INT,
FreeSpacePct VARCHAR(7),
FreeSpacePages INT,
PollDate datetime) 

DECLARE @command VARCHAR(5000) 

SELECT @command = 'Use [' + '?' + '] SELECT
@@servername as ServerName,
' + '''' + '?' + '''' + ' AS DatabaseName,
CAST(sysfiles.size/128.0 AS int) AS FileSize,
sysfiles.name AS LogicalFileName, sysfiles.filename AS PhysicalFileName,
CONVERT(sysname,DatabasePropertyEx(''?'',''Status'')) AS Status,
CONVERT(sysname,DatabasePropertyEx(''?'',''Updateability'')) AS Updateability,
CONVERT(sysname,DatabasePropertyEx(''?'',''Recovery'')) AS RecoveryMode,
CAST(sysfiles.size/128.0 - CAST(FILEPROPERTY(sysfiles.name, ' + '''' +
       'SpaceUsed' + '''' + ' ) AS int)/128.0 AS int) AS FreeSpaceMB,
CAST(100 * (CAST (((sysfiles.size/128.0 -CAST(FILEPROPERTY(sysfiles.name,
' + '''' + 'SpaceUsed' + '''' + ' ) AS int)/128.0)/(sysfiles.size/128.0))
AS decimal(4,2))) AS varchar(8)) + ' + '''' + '%' + '''' + ' AS FreeSpacePct,
GETDATE() as PollDate FROM dbo.sysfiles'
INSERT INTO @DBInfo
   (ServerName,
   DatabaseName,
   FileSizeMB,
   LogicalFileName,
   PhysicalFileName,
   Status,
   Updateability,
   RecoveryMode,
   FreeSpaceMB,
   FreeSpacePct,
   PollDate)
EXEC sp_MSForEachDB @command 

SELECT
   ServerName,
   DatabaseName,
   FileSizeMB,
   LogicalFileName,
   PhysicalFileName,
   Status,
   Updateability,
   RecoveryMode,
   FreeSpaceMB,
   FreeSpacePct,
   PollDate
FROM @DBInfo
ORDER BY
   ServerName,
   DatabaseName </pre>
</p>
<p>其实唯一吸引我的是EXEC sp_MSForEachDB这一句, 原来还可以这样用... 害我一直自己傻了吧唧地写循环. 实际上, 除了sp_MSForEachDB, 还有sp_MSForEachTable的用法. </p>
<p>另外, 上面的那段脚本在SQL Server 2000里面是执行不通的, 在2000的版本中, 不允许直接用exec的结果集做为插入的数据源集. 我稍微改了一下. 把插入数据的动作直接放到exec sp_MSForEachDB 里. 结果集用临时表做暂存,这样就通用了:</p>
<p><pre class="sql" name="code">create TABLE #DBInfo
( ServerName VARCHAR(100),
DatabaseName VARCHAR(100),
FileSizeMB INT,
LogicalFileName sysname,
PhysicalFileName NVARCHAR(520),
Status sysname,
Updateability sysname,
RecoveryMode sysname,
FreeSpaceMB INT,
FreeSpacePct VARCHAR(7),
FreeSpacePages INT,
PollDate datetime) 

DECLARE @command VARCHAR(5000) 

SELECT @command = 'INSERT INTO #DBInfo
   (ServerName,
   DatabaseName,
   FileSizeMB,
   LogicalFileName,
   PhysicalFileName,
   Status,
   Updateability,
   RecoveryMode,
   FreeSpaceMB,
   FreeSpacePct,
   PollDate)  SELECT
@@servername as ServerName,
' + '''' + '?' + '''' + ' AS DatabaseName,
CAST(sysfiles.size/128.0 AS int) AS FileSize,
sysfiles.name AS LogicalFileName, sysfiles.filename AS PhysicalFileName,
CONVERT(sysname,DatabasePropertyEx(''?'',''Status'')) AS Status,
CONVERT(sysname,DatabasePropertyEx(''?'',''Updateability'')) AS Updateability,
CONVERT(sysname,DatabasePropertyEx(''?'',''Recovery'')) AS RecoveryMode,
CAST(sysfiles.size/128.0 - CAST(FILEPROPERTY(sysfiles.name, ' + '''' +
       'SpaceUsed' + '''' + ' ) AS int)/128.0 AS int) AS FreeSpaceMB,
CAST(100 * (CAST (((sysfiles.size/128.0 -CAST(FILEPROPERTY(sysfiles.name,
' + '''' + 'SpaceUsed' + '''' + ' ) AS int)/128.0)/(sysfiles.size/128.0))
AS decimal(4,2))) AS varchar(8)) + ' + '''' + '%' + '''' + ' AS FreeSpacePct,
GETDATE() as PollDate FROM dbo.sysfiles' 

EXEC sp_MSForEachDB @command 

SELECT
   ServerName,
   DatabaseName,
   FileSizeMB,
   LogicalFileName,
   PhysicalFileName,
   Status,
   Updateability,
   RecoveryMode,
   FreeSpaceMB,
   FreeSpacePct,
   PollDate
FROM #DBInfo
ORDER BY
   ServerName,
   DatabaseName </pre>
</p>
<p>2. 用路径表述的父子关系在插入数据库时做约束</p>
<p>这个要求看起来有点变态, 实际上, 很多情况下, 我的感觉是, 这种确保数据关系安全的逻辑判断应该放在应用服务器或者中间层服务器上, 而不应当占用数据库的资源.</p>
<p>嗯, 这个命题和解法是在<a href="http://sqlblogcasts.com/blogs/simons/archive/2009/03/09/Enforcing-parent-child-relationship-with-Path-Hierarchy-model.aspx" target="_blank">sqlblogcasts</a>上看到. 脚本是这样的:</p>
<p>
<pre class="sql" name="code">create table Org (
  NodePath    varchar(200) not null primary key
, ParentPath  as cast(case when charindex('\',NodePath) = len(NodePath) then null
                           else left(NodePath,len(NodePath)-charindex('\',reverse(NodePath),2)+1)
                end as varchar(200)) persisted)

go

alter table Org add constraint fk_Org_ParentPath foreign key (ParentPath) references Org(NodePath)</pre>
</p>
<p>下面这些插入操作中,最后一笔由于不符合约束条件而失败.</p>
<p>
<pre class="sql" name="code">insert into Org values ('10\')
insert into Org values ('10\9\')
insert into Org values ('11\')
insert into Org values ('11\9\9\')</pre>
</p>
<p>对ParentPath的判断中, reverse方法我用的不多. 这让我想起了前阵子跟<a href="http://cyndi.snowrain.org"  class="alinks_links" onclick="return alinks_click(this);" title=""  style="padding-right: 13px; background: url(http://snow.snowrain.org/wp-content/plugins/alinks/images/external.png) center right no-repeat;" rel="external">Cyndi</a>讨论的手机号码来电和拨号时的显示匹配问题(因为很多时候我们会在号码前加前缀,+86,025,17951...). 也许反转过来的匹配就比较好做了.</p>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2009/03/20/sql-statements-list-data-files-and-enforcing-parent-child-relationship/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>解决MS SQL数据库孤立用户问题</title>
		<link>http://snow.snowrain.org/2009/02/12/mapping-ms-sql-server-database-orphaned-user-with-login-name/</link>
		<comments>http://snow.snowrain.org/2009/02/12/mapping-ms-sql-server-database-orphaned-user-with-login-name/#comments</comments>
		<pubDate>Thu, 12 Feb 2009 08:53:31 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/2009/02/12/mapping-ms-sql-server-database-orphaned-user-with-login-name/</guid>
		<description><![CDATA[新导入的数据库由于sysusers系统表缺失而导致数据库用户无法匹配到login user, 从而原有的账号无法使用, 重新创建也会因user name重名而报错. 查了一下MSDN, 可以用sp_change_users_login系统存储过程来修改, 但是直接对着一个刚刚restore的数据库用命令: sp_change_users_login 'AUTO_FIX', 'USERNAME' 报错 Msg 15600, Level 15, State 1, Procedure sp_change_users_login, Line 207 An invalid parameter or option was specified for procedure 'sys.sp_change_users_login'. 存储过程207行是这样的: if @Password IS Null begin raiserror(15600,-1,-1,'sys.sp_change_users_login') deallocate ms_crs_110_Users return (1) end 嗯, 仔细想想也不对, 再AUTO的命令, 系统里的用户也没法凭空创建出来, 再回头往下翻MSDN, 解了: EXEC sp_change_users_login 'AUTO_FIX', 'USERNAME', NULL, [...]]]></description>
			<content:encoded><![CDATA[<p>新导入的数据库由于sysusers系统表缺失而导致数据库用户无法匹配到login user, 从而原有的账号无法使用, 重新创建也会因user name重名而报错.</p>
<p>查了一下<a href="http://msdn.microsoft.com/en-us/library/aa259633(SQL.80).aspx">MSDN</a>, 可以用sp_change_users_login系统存储过程来修改, 但是直接对着一个刚刚restore的数据库用命令:</p>
<blockquote><p>sp_change_users_login 'AUTO_FIX', 'USERNAME'</p></blockquote>
<p>报错</p>
<blockquote><p>Msg 15600, Level 15, State 1, Procedure sp_change_users_login, Line 207<br />
An invalid parameter or option was specified for procedure 'sys.sp_change_users_login'.</p></blockquote>
<p>存储过程207行是这样的:</p>
<blockquote><p>if @Password IS Null<br />
begin<br />
raiserror(15600,-1,-1,'sys.sp_change_users_login')<br />
deallocate ms_crs_110_Users<br />
return (1)<br />
end</p></blockquote>
<p>嗯, 仔细想想也不对, 再AUTO的命令, 系统里的用户也没法凭空创建出来, 再回头往下翻MSDN, 解了:</p>
<blockquote><p>EXEC sp_change_users_login 'AUTO_FIX', 'USERNAME', NULL, 'PASSWORD'</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2009/02/12/mapping-ms-sql-server-database-orphaned-user-with-login-name/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>把那个瑜伽网站弄到在Firefox下面也可以看了</title>
		<link>http://snow.snowrain.org/2008/10/15/update-yoga-site/</link>
		<comments>http://snow.snowrain.org/2008/10/15/update-yoga-site/#comments</comments>
		<pubDate>Wed, 15 Oct 2008 14:59:13 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[软件网络]]></category>
		<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/?p=190</guid>
		<description><![CDATA[晚上去看前几天做的瑜伽网站theme(http://www.njwyhf.cn/). 点进去以后实在忍不住了, 正好洗完澡没事做, 把css下载下来改了几行, 加了对常用浏览器的支持, 现在应该可以在firefox下面看了~ 除了左边的那个flash广告. 嘿嘿.]]></description>
			<content:encoded><![CDATA[<p>晚上去看前几天做的瑜伽网站theme(http://www.njwyhf.cn/). 点进去以后实在忍不住了, 正好洗完澡没事做, 把css下载下来改了几行, 加了对常用浏览器的支持, 现在应该可以在firefox下面看了~ 除了左边的那个flash广告. 嘿嘿.</p>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2008/10/15/update-yoga-site/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ASP.NET设置Form的默认按钮</title>
		<link>http://snow.snowrain.org/2008/07/17/default-button-for-asp-dot-net-form/</link>
		<comments>http://snow.snowrain.org/2008/07/17/default-button-for-asp-dot-net-form/#comments</comments>
		<pubDate>Thu, 17 Jul 2008 15:11:30 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[软件网络]]></category>
		<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/?p=152</guid>
		<description><![CDATA[昨天在折腾一个查询系统的某一表单时, 遇到了这个问题. 当在表单中录入查询项之后敲回车, 默认聚焦不在查询提交的按钮上, 而是到了用户退出的按钮上.嗯, 这样的设计多多少少会造成些许不便, 考虑吃掉这只虫. 因为这个页面是继承于上层masterpage的. 而Form的定义也恰恰在masterpage中, 这样当masterpage顺位查找button的时候就默认聚焦在了退出按钮上, 这样用户每次录入查询项之后必须要小心翼翼地用鼠标去点提交才可以. 否则就变成直接清空cookie, 退出系统了. 如果要取消退出按钮的回车响应, 通常是加一段javascript, 当捕获到用户输入键KeyCode是13时, 返回false, 不响应单击事件: &#60;SCRIPT LANGUAGE="javascript"&#62; function SubmitKeyClick(button) { if (event.keyCode == 13) { Event.returnValue = false; } } &#60;/SCRIPT&#62; 然后在Page_Load事件中添加: tbInput.Attributes.Add("onkeydown","SubmitKeyClick('btnOK');"); 不过, .Net 2.0开始提供了一个设置Form默认按钮的属性: DefaultButton, 这样的话,从Content Page向上设置masterpage就可以了: this.Master.Page.Form.DefaultButton = "btnSubmit";]]></description>
			<content:encoded><![CDATA[<p>昨天在折腾一个查询系统的某一表单时, 遇到了这个问题. 当在表单中录入查询项之后敲回车, 默认聚焦不在查询提交的按钮上, 而是到了用户退出的按钮上.嗯, 这样的设计多多少少会造成些许不便, 考虑吃掉这只虫.</p>
<p>因为这个页面是继承于上层masterpage的. 而Form的定义也恰恰在masterpage中, 这样当masterpage顺位查找button的时候就默认聚焦在了退出按钮上, 这样用户每次录入查询项之后必须要小心翼翼地用鼠标去点提交才可以. 否则就变成直接清空cookie, 退出系统了.</p>
<p>如果要取消退出按钮的回车响应, 通常是加一段javascript, 当捕获到用户输入键KeyCode是13时, 返回false, 不响应单击事件:</p>
<pre name="code" class="javascript">&lt;SCRIPT LANGUAGE="javascript"&gt;
function SubmitKeyClick(button)
{
	if (event.keyCode == 13)
	{
		Event.returnValue = false;
	}
}
&lt;/SCRIPT&gt;
</pre>
<p>然后在Page_Load事件中添加:</p>
<pre name="code" class="c-sharp">tbInput.Attributes.Add("onkeydown","SubmitKeyClick('btnOK');");
</pre>
<p>不过, .Net 2.0开始提供了一个设置Form默认按钮的属性: DefaultButton, 这样的话,从Content Page向上设置masterpage就可以了:</p>
<pre name="code" class="c-sharp">this.Master.Page.Form.DefaultButton = "btnSubmit";
</pre>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2008/07/17/default-button-for-asp-dot-net-form/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>批量修改AD中的用户信息</title>
		<link>http://snow.snowrain.org/2008/06/15/batch-modify-user-info-inside-of-ad/</link>
		<comments>http://snow.snowrain.org/2008/06/15/batch-modify-user-info-inside-of-ad/#comments</comments>
		<pubDate>Sun, 15 Jun 2008 15:52:39 +0000</pubDate>
		<dc:creator>Snow.C</dc:creator>
				<category><![CDATA[软件网络]]></category>
		<category><![CDATA[工作备忘]]></category>

		<guid isPermaLink="false">http://snow.snowrain.org/?p=135</guid>
		<description><![CDATA[公司搬家了, AD中的用户信息需要修改一下, 比如地址, 电话, 传真什么的. MS有个命令行工具叫"LDIFDE", 用这玩意儿可以轻松搞定. 首先, 把AD中涉及到的用户导出来: ldifde -f all-users.ldf -s ADSERVER -d "OU=XXX,OU=XXX,OU=Domain Users,DC=XX,DC=XX,DC=XX" -p subtree -l "streetAddress,postalCode,telephoneNumber,facsimileTelephoneNumber" -r "(st=Jiang Su)" 最后的(st=Jiang Su)是一个filter, 也可以选择其他对象. 导出来的all-user.ldf可以用文本编辑器打开, 里面一行一行地记录了用户的信息. 很显然要对其进行修改, 但是直接修改里面的键值是不行的, 得指定其模式, 并且按照规定的文本格式重新排列. 比如一笔用户数据长这个样子: dn: CN=USER,OU=XX,OU=XXX,OU=XXX,OU=Domain Users,DC=XX,DC=XX,DC=XX changetype: add streetAddress: xxx, xxxxxx, xxxxxxx facsimileTelephoneNumber: +86 25 xxxxxx postalCode: 210008 telephoneNumber: +86 25 xxxxxx 若修改streetAddress,facsimileTelephoneNumber,postalCode,telephoneNumber四项, 需要按照这个格式来组织: [...]]]></description>
			<content:encoded><![CDATA[<p>公司搬家了, AD中的用户信息需要修改一下, 比如地址, 电话, 传真什么的.</p>
<p>MS有个命令行工具叫"<a href="http://support.microsoft.com/kb/555636/en-us" target="_blank">LDIFDE</a>", 用这玩意儿可以轻松搞定.</p>
<p>首先, 把AD中涉及到的用户导出来:</p>
<pre name="code" class="vb">ldifde -f all-users.ldf -s ADSERVER -d
"OU=XXX,OU=XXX,OU=Domain Users,DC=XX,DC=XX,DC=XX"
-p subtree
-l "streetAddress,postalCode,telephoneNumber,facsimileTelephoneNumber"
-r "(st=Jiang Su)"
</pre>
<p>最后的(st=Jiang Su)是一个filter, 也可以选择其他对象.</p>
<p>导出来的all-user.ldf可以用文本编辑器打开, 里面一行一行地记录了用户的信息. 很显然要对其进行修改, 但是直接修改里面的键值是不行的, 得指定其模式, 并且按照规定的文本格式重新排列.</p>
<p>比如一笔用户数据长这个样子:</p>
<pre name="code" class="vb">dn: CN=USER,OU=XX,OU=XXX,OU=XXX,OU=Domain Users,DC=XX,DC=XX,DC=XX
changetype: add
streetAddress: xxx, xxxxxx, xxxxxxx
facsimileTelephoneNumber: +86 25 xxxxxx
postalCode: 210008
telephoneNumber: +86 25 xxxxxx
</pre>
<p>若修改streetAddress,facsimileTelephoneNumber,postalCode,telephoneNumber四项, 需要按照这个格式来组织:</p>
<pre name="code" class="vb">dn: CN=USER,OU=XX,OU=XXX,OU=XXX,OU=Domain Users,DC=XX,DC=XX,DC=XX
changetype: modify
replace: streetAddress
streetAddress: NEW ADDRESS
-
replace: facsimileTelephoneNumber
facsimileTelephoneNumber: +86 25 NEW NUMBER
-
replace: postalCode
postalCode: 210012
-
replace: telephoneNumber
telephoneNumber: +86 25 NEW NUMBER
-
</pre>
<p>有了目标格式, 可以用多种途径将源数据文件修改成为可用的导入数据文件,可以编程替换, 也可以用一些功能强大的文本编辑工具直接正则表达式替换(因为telephoneNumber里面有分机信息, 每个人都不相同).</p>
<p>在将数据导入文件做好后, 就可以用下面的命令批量导入了:</p>
<pre name="code" class="vb">ldifde -i -f user-to-inport.ldf -s ADSERVER
</pre>
<p>过程中我遇到一些问题:<br />
1. 用户属性栏位字段的查找, 比如前面sample里面的<br />
"streetAddress,facsimileTelephoneNumber,postalCode,telephoneNumber",<br />
实际上, 我必须知道fax对应在AD中的字段是facsimileTelephoneNumber才可以将它导出;<br />
2. 在日常AD的使用中, 很多不规范的电话信息, 比如 +86 25 xxxxxx 和 +86-25-xxxxxx 这让我在批量查找替换的过程中费了不少事.</p>
<p>最后附一份默认schema下的AD用户属性栏位字段表(FROM <a href="http://edu.uuu.com.tw/ucomtips/011016.htm" target="_blank">HERE</a>):</p>
<pre name="code" class="vb">First name					sn
Last name						givenName
Initials						initials
Display name				displayName
description					description
Office							physicalDeliveryOfficeName
Telephone Number		telephoneNumber
E-mail							mail
Web page						wWWHomePage
Country/region			c
State/province			st
City								l
Street							streetAddress
Zip/Postal Code			postalCode
P.O. Box						postOfficeBox
User logon name			userPrincipalName
User logonname(pre-Windows 2000)		sAMAccountName
Profile path				profilePath
Logon script				scriptPath
Home folder					homeDirectory
Home								homePhone
Pager								pager
Mobile							mobile
Fax									facsimileTelephoneNumber
IP phone						ipPhone
Notes								info
Title								title
Department					department
Company							company
Manager							manager
Direct report				directReports
</pre>
]]></content:encoded>
			<wfw:commentRss>http://snow.snowrain.org/2008/06/15/batch-modify-user-info-inside-of-ad/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

