2007年2月21日 星期三

透明 Flash 語法

<EMBED style="LEFT: 0px; POSITION: absolute; TOP: 0px" align="center" src="要使用的Flash.swf " width="100%" height="100%" type=application/x-shockwave-flash ; quality="high" wmode="transparent">

讓表格在整個螢幕畫面的上下左右都是居中的方法

1. 在 BODY 中的屬性加入 leftmargin="0" topmargin="0", 即
<body leftmargin="0" topmargin="0">
2. 建立一個 Table 並將長寬都設為 100%, 類似下面的code
<table align="center" width="100%" height="100%">
<tr>
<td valign="absmiddle" align="center">
<img src="#" align="absmiddle" border="0">
</td>
</tr>
</table>

2007年2月18日 星期日

在 Blogger 加入最近發表的文章清單

1. 將下面紅色的yourblogname改成自己的blog名稱
http://yourblogname.blogspot.com/feeds/posts/default?alt=rss

2. 要先取得 RSS 轉 Javascript 的碼, 可以到下面這個網站取得http://itde.vccs.edu/rss2js/build.php
要填的東西不多, 只有六行
- URL: 填上你在上面步驟1裡的網址
- Show channel: 選 no
- Number of items to display: 看你想要在清單裡顯示幾則文章, 輸入一個數字
- Show item descriptions? How much: 輸入 0
- Show item posting date: 選 no
- Open links in a new window: 如果想要把文章開到新的窗口就選 yes, 否則就選 no
以上填好後, 按下 "Generate JavaScript" 按鈕後, 複製產生出來的碼

3. 到 Blogger 後台控制頁面: 範本 -> 網頁元素 -> "加入網頁元素" -> 在 "HTML/JavaScript" 按 "加入BLOG" 的按鈕 -> 把你在上面步驟2獲得的碼貼到 "內容", "書名" 自己取 (像我是取"最近的文章")

4. 完成!

2007年2月17日 星期六

隱藏 Blogger 上方的 Navbar

在 CSS 區 "]]></b:skin>" 的上面加上
#navbar-iframe {
height:0px;
visibility:hidden;
display:none
}

在文章裡顯示優質的程式碼

出處: 良人的大秘寶

1. 在CSS中加入 (</head>之前)
CODE {
display: block; /* fixes a strange ie margin bug */
font-family: Courier New;
font-size: 8pt;
overflow:auto;
background: #f0f0f0 url(http://klcintw.images.googlepages.com/Code_BG.gif) left top repeat-y;
border: 1px solid #ccc;
padding: 10px 10px 10px 21px;
max-height:200px;
line-height: 1.2em;
}


2. 使用方法: 在文章中將程式碼置於<code>及</code>的區塊中即可

3. 注意事項: 有些符號必須先轉換

2007年2月14日 星期三

固定網頁背景不隨捲軸動

body {
background: url("http://背景圖位址") ;
background-attachment: fixed;
}

利用CSS控制打印

<style>
@media print{
INPUT {display:none}
}
</style>
<TABLE border="0" style="font-size:9pt;" width="300px" align="center">
<THEAD style="display:table-header-group;font-weight:bold">
<TR><TD colspan="2" align="center" style="font-weight:bold;border:3px double red">每页都有的表头</TD></TR>
</THEAD>
<TBODY style="text-align:center"">
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR style="page-break-after:always;"><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR style="page-break-after:always;"><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR><TD>表格内容</TD><TD>表格内容</TD></TR>
<TR style="page-break-after:always;"><TD>表格内容</TD><TD>表格内容</TD></TR>
</TBODY>
<TFOOT style="display:table-footer-group;font-weight:bold">
<TR>
<TD colspan="2" align="center" style="font-weight:bold;border:3px double blue">每页都有的表尾</TD>
</TR>
</TFOOT>
</TABLE>
<input type=button value=" 打 印 " onclick="window.print()">

现有的Web打印控制技术分成几种方案

现有的Web打印控制技术分成几种方案
  自定义控件完成打印
  利用IE自带的WebBrowser控件实现打印
  利用第三方控件实现打印
以下主要谈前两个方面的内容

一、 自定义控件方式
自定义控件方式就是利用VB或VC等工具生成COM组件,用定义好的打印格式来分析打印源文件从而实现打印。只有将生成的组件下载并注册到客户机上,才能实现在客户端的打印。
难点主要是定义打印格式、如何来分析打印源文件。现有的比较好的方法是利用XML技术来全面的解决问题,利用XML可以非常容易地定义打印目标的文本、表格等内容的格式。但对程序员的开发要求高,难度比较大。

二、 利用WebBrowser实现Web打印
WebBrowser是IE内置的浏览器控件,无需用户下载。本文档所讨论的是有关IE6.0版本的WebBrowser控件技术内容。与其相关的技术要求有:打印文档的生成、页面设置、打印操作的实现等几个环节。

(一)、 打印文档的生成
1、 客户端脚本方式
客户端脚本分为VBScript、JavaScript、JScript几种脚本语言。在IE下开发应用使用的语法为JScript的语法,由于它和JavaScript几乎没有什么区别,所以也可以称其为JavaScript(下面简写为JS)。一般情况下,主要使用JS来实现DOM文档的分析,DOM为微软提出的一种Web文档模型,主要用来实现Web脚本编程。
利用JS可以分析源页面的内容,将欲打印的页面元素提取出来,实现打印。通过分析源文档的内容,可以生成打印目标文档。

优点:客户端独立完成打印目标文档的生成,减轻服务器负荷;
缺点:源文档的分析操作复杂,并且源文档中的打印内容要有约定;

2、 服务器端程序方式
服务器端程序方式,主要是利用后台代码从数据库中读取打印源,生成打印目标文档。当的页面生成时,还应适当考虑使用CSS来实现强制分页控制。

优点:可以生成内容非常的丰富的打印目标文档,目标文档的内容的可控性强。由于打印内容是从数据库中获取的,所以生成操作相对简单;
缺点:服务器端负载比较大;

(二)、 页面设置
页面设置主要是指设置打印文档的页边距、页眉、页脚、纸张等内容。页面设置将直接影响到打印文档版面的生成效果,所以它和打印文档的生成有着密切的关系。比如:表格的行数、大小、位置、字体的大小等。
现有的技术是利用IE6.0内置的打印模板方式来控制页面设置,其可以对打印目标文档产生非常大的影响。打印模板可以控制页边距、页眉、页脚、奇偶页等内容,并可以将用户的设置取得,还可以将设置发送到服务器端。
打印模板技术可以自定预览窗口和打印格式,最大限度地影响目标文档和打印效果。

(三)、 打印操作的实现
此功能的实现主要是利用WebBrowser控件的函数接口来实现打印、打印预览(默认的)、页面设置(默认的)。
<object ID='WebBrowser1' WIDTH=0 HEIGHT=0
CLASSID='CLSID:8856F961-340A-11D0-A96B-00C04FD705A2'>
//打印
WebBrowser1.ExecWB(6,1);
//打印设置
WebBrowser1.ExecWB(8,1);
//打印预览
WebBrowser1.ExecWB(7,1);


三、 本项目采用的打印方案
服务器端程序方式、打印预览接口调用,下面为例,主要参考项目中的:pageErrorPrint.aspx.vb文件
主调用页
function PrintPage(iPageIndex,strQuery)
{
var strURL;
strURL = "PageErrorPrint.aspx?PageIndex=" + iPageIndex + "&QueryString=" + strQuery;
winPrint=window.open(strURL,"","left=2000,top=2000,fullscreen=3");
}


打印页HTML源中的预览控制
<SCRIPT language="javascript">function print(){
document.write("<object ID='WebBrowser' WIDTH=0 HEIGHT=0
CLASSID='CLSID:8856F961-340A-11D0-A96B-00C04FD705A2'></object>");
WebBrowser.ExecWB(7,1);
window.opener=null;
window.close();}
</SCRIPT>

Web 列印控制

ASP开发必备:WEB打印代码大全这篇文章主要介绍了如何使用ASP控制Web的各种打印效果,它能够控制纵打、横打和页面边距等。
1、控制"纵打"、 "横打"和"页面的边距"。
(1)

  <script defer>
  function SetPrintSettings() {
  // -- advanced features
  factory.printing.SetMarginMeasure(2) // measure margins in inches
  factory.SetPageRange(false, 1, 3) // need pages from 1 to 3
  factory.printing.printer = "HP DeskJet 870C"
  factory.printing.copies = 2
  factory.printing.collate = true
  factory.printing.paperSize = "A4"
  factory.printing.paperSource = "Manual feed"

  // -- basic features
  factory.printing.header = "This is MeadCo"
  factory.printing.footer = "Advanced Printing by ScriptX"
  factory.printing.portrait = false
  factory.printing.leftMargin = 1.0
  factory.printing.topMargin = 1.0
  factory.printing.rightMargin = 1.0
  factory.printing.bottomMargin = 1.0
  }
  </script>

(2)

  <script language="javascript">
  function printsetup(){
  // 打印页面设置
  wb.execwb(8,1);
  }
  function printpreview(){
  // 打印页面预览
  wb.execwb(7,1);
  }
  function printit()
  {
  if (confirm('确定打印吗?')) {
  wb.execwb(6,6)
  }
  }
  </script>
  </head>
  <body>

<OBJECT classid="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2" height=0 id=wb name=wb width=0></OBJECT>
  <input type=button name=button_print value="打印" onclick="javascript:printit()">
  <input type=button name=button_setup value="打印页面设置" onclick="javascript:printsetup();">
  <input type=button name=button_show value="打印预览" onclick="javascript:printpreview();">
  <input type=button name=button_fh value="关闭" onclick="javascript:window.close();">

  ------------------------------------------------
  关于这个组件还有其他的用法,列举如下:
  WebBrowser.ExecWB(1,1) 打开
  Web.ExecWB(2,1) 关闭现在所有的IE窗口,并打开一个新窗口
  Web.ExecWB(4,1) 保存网页
  Web.ExecWB(6,1) 打印
  Web.ExecWB(7,1) 打印预览
  Web.ExecWB(8,1) 打印页面设置
  Web.ExecWB(10,1) 查看页面属性
  Web.ExecWB(15,1) 好像是撤销,有待确认
  Web.ExecWB(17,1) 全选
  Web.ExecWB(22,1) 刷新
  Web.ExecWB(45,1) 关闭窗体无提示

2、分页打印

<HTML>
<HEAD>
<STYLE>
P {page-break-after: always}
</STYLE>
</HEAD>
<BODY>
<%while not rs.eof%>
<P><%=rs(0)%></P>
<%rs.movenext%>
<%wend%>
</BODY>
</HTML>

3、ASP页面打印时如何去掉页面底部的路径和顶端的页码编号
(1)ie的文件-〉页面设置-〉讲里面的页眉和页脚里面的东西都去掉,打印就不出来了。
(2)

<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="YC">
<script language="VBScript">
  dim hkey_root,hkey_path,hkey_key
  hkey_root="HKEY_CURRENT_USER"
  hkey_path="\Software\Microsoft\Internet Explorer\PageSetup"
  '//设置网页打印的页眉页脚为空
  function pagesetup_null()
  on error resume next
  Set RegWsh = CreateObject("WScript.Shell")
  hkey_key="\header"  
  RegWsh.RegWrite hkey_root+hkey_path+hkey_key,""
  hkey_key="\footer"
  RegWsh.RegWrite hkey_root+hkey_path+hkey_key,""
  end function
  '//设置网页打印的页眉页脚为默认值
  function pagesetup_default()
  on error resume next
  Set RegWsh = CreateObject("WScript.Shell")
  hkey_key="\header"  
  RegWsh.RegWrite hkey_root+hkey_path+hkey_key,"&w&b页码,&p/&P"
  hkey_key="\footer"
  RegWsh.RegWrite hkey_root+hkey_path+hkey_key,"&u&b&d"
  end function
  </script>
</HEAD>
<BODY>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/><p align=center>
<input type="button" value="清空页码" onclick=pagesetup_null()> <input type="button" value="恢复页吗" onclick=pagesetup_default()><br/>
</p>
</BODY>
</HTML>

4、浮动帧打印

  <SCRIPT LANGUAGE=javascript>
  function button1_onclick() {
  var odoc=window.iframe1.document;
  var r=odoc.body.createTextRange();
  var stxt=r.htmlText;
  alert(stxt)
  var pwin=window.open("","print");
  pwin.document.write(stxt);
  pwin.print();
  }
  </script>

5、用FileSystem组件实现WEB应用中的本地特定打印

  <script Language=VBScript>
  function print_onclick //打印函数
  dim label
  label=document.printinfo.label.value //获得HTML页面的数据
  set objfs=CreateObject("Scripting.FileSystemObject") //创建FileSystem组件对象的实例
  set objprinter=objfs.CreateTextFile ("LPT1:",true) //建立与打印机的连接
  objprinter.Writeline("__________________________________") //输出打印的内容
  objprinter.Writeline("| |")
  objprinter.Writeline("| 您打印的数据是:"&label& " |”)
  objprinter.Writeline("| |")
  objprinter.Writeline("|_________________________________|")
  objprinter.close //断开与打印机的连接
  set objprinter=nothing
  set objfs=nothing // 关闭FileSystem组件对象
  end function
  </script>

  服务器端脚本:
  <%………
  set conn=server.CreateObject ("adodb.connection")
  conn.Open "DSN=name;UID=XXXX;PWD=XXXX;"
  set rs=server.CreateObject("adodb.recordset")
  rs.Open(“select ……”),conn,1,1
  ……….%> //与数据库进行交互

  HTML页面编码:
  <HTML>
  ………
  <FORM ID=printinfo NAME="printinfo" >
  <INPUT type="button" value="打印>>" id=print name=print > //调用打印函数
  <INPUT type=hidden id=text1 name=label value=<%=………%>> //保存服务器端传来的数据
  ………
  </HTML>

中文直排顯示


<DIV style="DIRECTION: ltr; WRITING-MODE: tb-rl; HEIGHT: 400px">
文字
</DIV>

新細明體

<DIV style='writing-mode:tb-rl; font-family: "新細明體"'>
直排的字
</DIV>

Access 的資料庫安全小Tip

通常我們寫小程式時,常會選擇ACCESS當作資料庫,您知道這是會被下載的嗎?


如題:

 通常我們在寫一些小程式,或者是說沒有自己的主機必須使用免費的空間,這時候我們會用ACCESS資料庫(.MDB),當作儲存的資料庫,因為使用簡單,大多數免費空間也都只支援這個東西,而您知道嗎?只要不小心洩漏了您的資料庫位置,這個資料庫是會被下載下來的。

 尤其當資料庫存放的是敏感性資料,像是帳號之類的,那接下來就是要您擔心一下網站的安全囉,那是不是就沒有辦法了呢?當然不是,ASP有一個方便的特性,就是使用的資料庫只要本身是ACCESS資料結構,搭配好正確的連結語法。

 例如說我本來使用的資料庫檔名為DATA.MDB,但是我把它改為DATA.ASP好了,不要以為這樣就無法使用,錯囉~只要連結的檔名正確,還是一樣可以使用而且不用擔心資料格式會有問題,因為ASP程式會用原本資料庫結構下去執行讀取修改功能,只要您不要隨意修改更改過檔案格式的資料庫,那就不會有任何問題。

 看到我剛剛使用.asp當作副檔名,是不是會有人想,對吼!我把它改成ASP就不會被下載了啦,告訴您,您只對了一半,為什麼這樣說呢,因為ASP不會被解讀原始碼是因為它的原始碼是用 包起來,伺服器再轉換時看到開頭 作結束。

 而單純將資料庫改成ASP格式是沒有用的,伺服器會直接跳過沒有 的地方不轉換,直接給他顯示出來,而檔案本身結構沒有改變就會直接在瀏覽器上顯示,把它當作文字檔案顯示出來,就算是改成其他怪怪的檔案也是如此,除非是經由伺服器上的設定來尋找,否則用個簡單的瀏覽器直接下載或者是續傳軟體給他慢慢抓,都是可以輕易地將資料庫抓下來。

 被抓下來的資料庫就算有鎖密碼,還是很容易被破解,所以總結一句話,必須在瀏覽器出現時更改過內容,否則都會被下載,顧慮到免費空間的關係,所以找了一個最簡單的方法,怎樣改?改成.htw就可以了,為什麼呢?因為IIS原始設定中,有個預設執行副檔名,可以針對各種副檔案名作處理動作,其中htw是一種特殊格式,而該檔案內容必須參照一定的格式開頭,而改過的資料庫因為絕對不可能符合,所以會在瀏覽器上出現錯誤畫面,也就隱藏掉了資料庫內容,這個方法在免費asp空間上也可以使用,因為IIS預設就會有該設定,這樣就絕對不怕會被抓到資料庫啦。

ASP程式碼把圖片上傳至資料庫

除了運用另外下載的元件以外,ASP本身也有能力把一張圖片上傳到一般資料庫去‧ 感興趣的網友不要錯過喔!


用純ASP代碼實現圖片上傳并存入數據庫中
用ASP編寫網站應用程序時間長了﹐難免會遇到各式各樣的問題﹐其中關于如何上傳文件到服務器恐怕是遇見最多的問題了﹐尤其是上傳圖片﹐比如你想要在自己的社區里面實現類似網易虛擬社區提供的“每日一星”的功能﹐就要提供給網友上傳照片的功能。上傳圖片文件到服務器可以使用各種免費的文件上傳組件﹐使用起來功能雖然很強大﹐但是由于很多情況下﹐我們只能使用免費的支持ASP的空間或者租用別人的虛擬空間﹐對于第一種情況﹐我們根本就沒有可能來使用文件上傳組件﹔至于第二種情況﹐我們也要付出不少的“銀子”才可以。除非你擁有自己的虛擬主機﹐你就可以隨便的在服務器上面安裝自己所需要的組件﹐這種情況對于大多數人來說是可望而不可及的。那我們就沒有辦法了嗎﹖呵呵﹐答案是肯定的〔當然是肯定的了﹐要不然我也沒法寫出這篇文章啊〕。下面就讓我們一起來使用純ASP代碼來實現圖片的上傳以及保存到數據庫的功能〔順便也實現顯示數據庫中的圖片到網頁上的功能〕。

首先我們先來熟悉一下將要使用的對象方法。我們用來獲取上一個頁面傳遞過來的數據一般是使用Request對象。同樣的﹐我們也可以使用Request對象來獲取上傳上來的文件數據﹐使用的方法是Request.BinaryRead()。而我們要從數據庫中讀出來圖片的數據顯示到網頁上面要用到的方法是﹕

Request.BinaryWrite()。在我們得到了圖片的數據﹐要保存到數據庫中的時候﹐不可以直接使用Insert語句對數據庫進行操作﹐而是要使用ADO的AppendChunk方法﹐同樣的﹐讀出數據庫中的圖片數據﹐要使用GetChunk方法。各個方法的具體語法如下﹕

* Request.BinaryRead語法﹕

variant = Request.BinaryRead(count)

參數

variant

返回值保存著從客戶端讀取到數據。

count

指明要從客戶端讀取的數據量大小﹐這個值小于或者等于使用方法Request.TotalBytes得到的數據量。

* Request.BinaryWrite語法﹕

Request.BinaryWrite data

參數

data

要寫入到客戶端瀏覽器中的數據包。

* Request.TotalBytes語法﹕

variant = Request.TotalBytes

參數

variant

返回從客戶端讀取到數據量的字節數。

* AppendChunk語法

將數據追加到大型文本﹑二進制數據 Field 或 Parameter 對象。

object.AppendChunk Data

參數

object Field 或 Parameter 對象

Data 變體型﹐包含追加到對象中的數據。

說明

使用 Field 或 Parameter 對象的 AppendChunk 方法可將長二進制或字符數據填寫到對象中。在系統內存有限的情況下﹐可以使用 AppendChunk 方法對長整型值進行部分而非全部的操作。

* GetChunk語法

返回大型文本或二進制數據 Field 對象的全部或部分內容 。

variable = field.GetChunk( Size )

返回值

返回變體型。

參數

Size 長整型表達式﹐等于所要檢索的字節或字符數。

說明

使用 Field 對象的 GetChunk 方法檢索其部分或全部長二進制或字符數據。在系統內存有限的情況下﹐可使用 GetChunk 方法處理部分而非全部的長整型值。

GetChunk 調用返回的數據將賦給“變量”。如果 Size 大于剩余的數據﹐則GetChunk 僅返回剩余的數據而無需用空白填充“變量”。如果字段為空﹐則GetChunk 方法返回 Null。

每個后續的 GetChunk 調用將檢索從前一次 GetChunk 調用停止處開始的數據。但是﹐如果從一個字段檢索數據然后在當前記錄中設置或讀取另一個字段的值﹐ADO 將認為已從第一個字段中檢索出數據。如果在第一個字段上再次調用 GetChunk 方法﹐ADO 將把調用解釋為新的 GetChunk 操作并從記錄的起始處開始讀取。如果其他 Recordset 對象不是首個 Recordset 對象的副本﹐則訪問其中的字段不會破壞 GetChunk 操作。

如果 Field 對象的 Attributes 屬性中的 adFldLong 位設置為 True﹐則可以對該字段使用 GetChunk 方法。

如果在 Field 對象上使用 Getchunk 方法時沒有當前記錄﹐將產生錯誤 3021

〔無當前記錄〕。

接下來﹐我們就要來設計我們的數據庫了﹐作為測試我們的數據庫結構如下〔Access97〕﹕

字段名稱    類型    描述

  id    自動編號   主鍵值

img OLE對象   用來保存圖片數據 


對于在MS SQL Server7中﹐對應的結構如下﹕

字段名稱    類型    描述

  id     int(Identity) 主鍵值

img   image     用來保存圖片數據 


現在開始正式編寫我們的純ASP代碼上傳部分了﹐首先﹐我們有一個提供給用戶的上傳界面﹐可以讓用戶選擇要上傳的圖片。代碼如下
upload.htm﹕

<html>

<body>

<center>

<form name="mainForm" enctype="multipart/form-data" action="process.asp" method=post>

<input type=file name=mefile><br>

<input type=submit name=ok value="OK">

</form>

</center>

</body>

</html>


注意代碼中黑色斜體的部分﹐一定要在Form中有這個屬性﹐否則﹐將無法得到上傳上來的數據。

接下來﹐我們要在process.asp中對從瀏覽器中獲取的數據進行必要的處理﹐因為我們在process.asp中獲取到的數據不僅僅包含了我們想要的上傳上來的圖片的數據﹐也包含了其他的無用的信息﹐我們需要剔除冗余數據﹐并將處理過的圖片數據保存到數據庫中﹐這里我們以Access97為例。具體代碼如下process.asp﹕

<%

response.buffer=true

formsize=request.totalbytes

formdata=request.binaryread(formsize)

bncrlf=chrB(13) & chrB(10)

divider=leftB(formdata,clng(instrb(formdata,bncrlf))-1)

datastart=instrb(formdata,bncrlf & bncrlf)+4

dataend=instrb(datastart+1,formdata,divider)-datastart

mydata=midb(formdata,datastart,dataend)


set connGraph=server.CreateObject("ADODB.connection")

connGraph.ConnectionString="driver={Microsoft Access Driver (*.mdb)};DBQ=" &

server.MapPath("images.mdb") & ";uid=;PWD=;"

connGraph.Open


set rec=server.createobject("ADODB.recordset")

rec.Open "SELECT * FROM [images] where id is null",connGraph,1,3

rec.addnew

rec("img").appendchunk mydata

rec.update

rec.close

set rec=nothing

set connGraph=nothing

%>


好了﹐這下我們就把上傳來的圖片保存到了名為images.mdb的數據庫中了﹐剩下的工作就是要將數據庫中的圖片數據顯示到網頁上面了。一般在HTML中﹐顯示圖片都是使用<IMG>標簽﹐也就是<IMG SRC="圖片路徑">﹐但是我們的圖片是保存到了數據庫中﹐“圖片路徑”是什么呢﹖呵呵﹐其實這個SRC屬性除了指定路徑外﹐也可以這樣使用哦﹕

<IMG SRC="showimg.asp?id=xxx">

所以﹐我們所要做的就是在showimg.asp中從數據庫中讀出來符合條件的數據﹐并返回到SRC屬性中就可以了﹐具體代碼如下
showimg.asp﹕
<%

set connGraph=server.CreateObject("ADODB.connection")

connGraph.ConnectionString="driver={Microsoft Access Driver (*.mdb)};DBQ=" &

server.MapPath("images.mdb") & ";uid=;PWD=;"

connGraph.Open

set rec=server.createobject("ADODB.recordset")

strsql="select img from images where id=" & trim(request("id"))

rec.open strsql,connGraph,1,1

Response.ContentType = "image/*"

Response.BinaryWrite rec("img").getChunk(7500000)

rec.close

set rec=nothing

set connGraph=nothing

%>


注意在輸出到瀏覽器之前一定要指定Response.ContentType = "image/*"﹐以便正常顯示圖片。

最后要注意的地方是﹐我的process.asp中作的處理沒有考慮到第一頁(upload.htm)中還有其他數據﹐比如<INPUT type=tesxt name=userid>等等﹐如果有這些項目﹐你的process.asp就要注意處理掉不必要的數據。

怎么樣﹐其實上傳圖片并保存到數據庫很簡單吧﹐這樣再也不用為自己的空間無法使用各類的上傳組件發愁了吧。還等什么﹖趕快試一試吧。


〔以上所有程序均在WinNT4.0﹐IIS4﹐Access97/MS SQL Server7.0中運行通過〕

利用 Case 敘述做 SQL 的動態排列

SQL Server 在讀取資料時是採用隨機的方式, 所以使用者會用 Order 子句來做資料排列, 在這篇文章當中咱叨要來進一步介紹按怎使用 Case 來做動態的排列

Order By 子句

咱先來看麥一般使用 Select 的結果, 在這篇文章的例咱會使用 SQL Server 的北風資料庫, 請打開 Query Analyzer, 執行


Use Northwind
Go
Select CompanyName, ContactName, ContactTitle
From Customers


執行的結果可能是按照資料輸入的時間來排列, 哪是你要照自己的規則來排, 你叨需要用到 Order By 子句, 譬如講前一個例, 你哪是要照公司名來排叨要按呢做


Select CompanyName, ContactName, ContactTitle
From Customers
Order By CompanyName


Case 敘述

Case 敘述適用來控制程式的流向, 所以咱叨要利用 Case 敘述來做 T-SQL 的邏輯控制, 來看麥 Case 的語法


Case <input expression>
When <when expression> Then <result expression>
[...n]
[Else <result expression>]


光看語法不夠, 現在用一個例來學練一下, 同款地咱還是用北風資料庫, 假設咱們要將職員 (Employees) 資料表中的英文稱呼改做台灣式, 可以按呢做


select FirstName, TitleOfCourtesy, CourtesyInTC =
Case TitleOfCourtesy
When 'Ms.' Then '水姑娘'
When 'Dr.' Then '博士博'
When 'Mr.' Then '先仔'
When 'Mrs.' Then '女士'
Else '先生/小姐'
End
From employees


動態排列

瞭解了基本語法後咱們就可以開始學習按怎利用 Order By 加上 Case 敘述來做動態的資料排列


Declare @OrderKey TinyInt
Set @OrderKey = 2

Select CompanyName, ContactName, ContactTitle
From Customers
Order By Case
When @OrderKey = 1 Then CompanyName
When @OrderKey = 2 Then ContactName
Else ContactTitle
End


不過這親像還不太實用, 至少在 ASP 中, 所以接下來咱來做一個預儲程式


Create Procedure sp_SelectCustomersDynamicOrder
@OrderKey = Null
As
Select CompanyName, ContactName, ContactTitle
From Customers
Order By Case
When @OrderKey = 1 Then CompanyName
When @OrderKey = 2 Then ContactName
Else ContactTitle
End


現在你就可以在直接呼叫這個 Stored Procedure


exec sp_SelectCustomersDynamicOrder
exec sp_SelectCustomersDynamicOrder 1
exec sp_SelectCustomersDynamicOrder 2


按呢是不是友善多了

希望這篇文章對你有幫助!

關於IFRAME 自適應高度的研究

代碼如下:


<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>New Page 1</title>
</head>
<body>
<IFRAME id="test" name="test" frameBorder=0 scrolling=no src="http://10.107.2.199:2500/cn/asp/reg.asp" width="100%" height=0></IFRAME>
</body>
</html>
<SCRIPT FOR=window EVENT=onload LANGUAGE="JScript">
document.all("test").height=test.document.body.scrollHeight;
</SCRIPT>


重要提示:src=中你必須填寫的網頁地址,一定要和本頁面在同一個站點上,否則,會抱錯,說“拒絕訪問!”

之前自己也碰到過這個問題,爲了得到答案去網上搜索,發現有不少人也遇到了這樣的問題,現在就把解決方法共用一下,超簡單哦

1、建立一個bottom.js的文件,然後輸入下面的代碼(只有兩行哦)

parent.document.all("框架ID名").style.height=document.body.scrollHeight;
parent.document.all("框架ID名").style.width=document.body.scrollWidth;


這裏的 框架ID名 就是Iframe的ID,比如:
<IFRAME id="框架ID名" name="left" frameBorder=0 scrolling=no src="XXX.asp" width="100%"></IFRAME>

2、給你網站裏所有的被包含文件裏面每個都加入

<script language = "JavaScript" src = "bottom.js"/></script>


3、OK,收工!

我在WINXP、IE6下面測試通過。很簡單吧!
----------------------------------------------
Iframe自適應高度

<script language="JavaScript">
//** iframe自動適應頁面 **//
//輸入你希望根據頁面高度自動調整高度的iframe的名稱的列表
//用逗號把每個iframe的ID分隔. 例如: ["myframe1", "myframe2"],可以只有一個表單,則不用逗號。
//定義iframe的ID
var iframeids=["content"]
//如果用戶的瀏覽器不支援iframe是否將iframe隱藏 yes 表示隱藏,no表示不隱藏
var iframehide="yes"
function dyniframesize()
{
var dyniframe=new Array()
for (i=0; i<iframeids.length; i++)
{
if (document.getElementById)
{
//自動調整iframe高度
dyniframe[dyniframe.length] = document.getElementById(iframeids[i]);
if (dyniframe[i] && !window.opera)
{
dyniframe[i].style.display="block"
if (dyniframe[i].contentDocument && dyniframe[i].contentDocument.body.offsetHeight) //如果用戶的瀏覽器是NetScape
dyniframe[i].height = dyniframe[i].contentDocument.body.offsetHeight;
else if (dyniframe[i].Document && dyniframe[i].Document.body.scrollHeight) //如果用戶的瀏覽器是IE
dyniframe[i].height = dyniframe[i].Document.body.scrollHeight;
}
}
//根據設定的參數來處理不支援iframe的瀏覽器的顯示問題
if ((document.all || document.getElementById) && iframehide=="no")
{
var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i])
tempobj.style.display="block"
}
}
}
if (window.addEventListener)
window.addEventListener("load", dyniframesize, false)
else if (window.attachEvent)
window.attachEvent("onload", dyniframesize)
else
window.onload=dyniframesize
</script>

精妙SQL語句介紹

說明:複製表(只複製結構,源表名:a 新表名:b)
select * into b from a where 1<>1

說明:拷貝表(拷貝資料,源表名:a 目標表名:b)
insert into b(a, b, c) select d,e,f from b;

說明:顯示文章、提交人和最後回復時間
select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b  

說明:外連接查詢(表名1:a 表名2:b)
select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c

說明:日程安排提前五分鐘提醒
select * from 日程安排 where datediff('minute',f開始時間,getdate())>5

說明:兩張關聯表,刪除主表中已經在副表中沒有的資訊
delete from info where not exists ( select * from infobz where info.infid=infobz.infid )

說明:--

SELECT A.NUM, A.NAME, B.UPD_DATE, B.PREV_UPD_DATE FROM TABLE1,(SELECT X.NUM, X.UPD_DATE, Y.UPD_DATE PREV_UPD_DATE FROM (SELECT NUM, UPD_DATE, INBOUND_QTY, STOCK_ONHAND FROM TABLE2 WHERE TO_CHAR(UPD_DATE,'YYYY/MM') = TO_CHAR(SYSDATE, 'YYYY/MM')) X, (SELECT NUM, UPD_DATE, STOCK_ONHAND FROM TABLE2 WHERE TO_CHAR(UPD_DATE,'YYYY/MM') = TO_CHAR(TO_DATE(TO_CHAR(SYSDATE, 'YYYY/MM') ¦¦ '/01','YYYY/MM/DD') - 1, 'YYYY/MM') ) Y, WHERE X.NUM = Y.NUM (+)AND X.INBOUND_QTY + NVL(Y.STOCK_ONHAND,0) <> X.STOCK_ONHAND ) B WHERE A.NUM = B.NUM


說明:--

select * from studentinfo where not exists(select * from student where studentinfo.id=student.id) and 系名稱='"&strdepartmentname&"' and 專業名稱='"&strprofessionname&"' order by 性別,生源地,高考總成績


說明: 從資料庫中去一年的各單位電話費統計(電話費定額賀電化肥清單兩個表來源)
SELECT a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy') AS telyear, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '01', a.factration)) AS JAN, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '02', a.factration)) AS FRI, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '03', a.factration)) AS MAR, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '04', a.factration)) AS APR, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '05', a.factration)) AS MAY, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '06', a.factration)) AS JUE,SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '07', a.factration)) AS JUL, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '08', a.factration)) AS AGU, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '09', a.factration)) AS SEP, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '10', a.factration)) AS OCT, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '11', a.factration)) AS NOV,SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '12', a.factration)) AS DEC FROM (SELECT a.userper, a.tel, a.standfee, b.telfeedate, b.factration FROM TELFEESTAND a, TELFEE b WHERE a.tel = b.telfax) a GROUP BY a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy')

說明:四表聯查問題:
select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....

說明:得到表中最小的未使用的ID號

SELECT (CASE WHEN EXISTS(SELECT * FROM Handle b WHERE b.HandleID = 1) THEN MIN(HandleID) + 1 ELSE 1 END) as HandleID FROM Handle WHERE NOT HandleID IN (SELECT a.HandleID - 1 FROM Handle a)

將兩張表的某幾個欄位的所有行插入到第三張表的指定欄位裡

例如:現有表TA、TB 、TC,現要把TA的 colA欄位和TC的colC欄位的所有行(TA.colA和TC.colC行數相同)分別插入到TB的colA和colC欄位,TA.colB和表TC的colB欄位關聯

insert into TB (colA,colB)
select TA.colA, TC.colB from TA inner join TC on TA.colB=TC.colB

另一個分頁的 Store Procedure


CREATE PROCEDURE search_sp
@tblName varchar(255), -- 表名
@strGetFields varchar(1000) = '*', -- 需要返回的列
@fldName varchar(255)='', -- 排序的欄位名
@PageSize int = 10, -- 頁尺寸
@PageIndex int = '', -- 頁碼
@doCount bit = 0, -- 返回記錄總數, 非 0 值則返回
@OrderType bit = '', -- 設置排序類型, 非 0 值則降冪
@strWhere varchar(1500) = '' -- 查詢條件 (注意: 不要加 where)
AS

declare @strSQL nvarchar(4000) -- 主語句
declare @strTmp varchar(110) -- 臨時變數
declare @strOrder varchar(400) -- 排序類型
if @doCount != 0
begin
if @strWhere !=''
set @strSQL = 'select count(1) as Total from [' + @tblName + '] where '+@strWhere
else
set @strSQL = 'select count(1) as Total from [' + @tblName + ']'
end
--以上代碼的意思是如果@doCount傳遞過來的不是0,就執行總數統計。以下的所有代碼都是@doCount爲0的情況

else
begin
if @OrderType != 0
begin
set @strTmp = '< (select min'
set @strOrder = ' order by [' + @fldName +'] desc'
--如果@OrderType不是0,就執行降冪,這句很重要!
end

else
begin
set @strTmp = '> (select max'
set @strOrder = ' order by [' + @fldName +'] asc'
end
if @PageIndex = 1
begin
if @strWhere != ''
set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from [' + @tblName + '] where ' + @strWhere + ' ' + @strOrder
else
set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from ['+ @tblName + '] '+ @strOrder
--如果是第一頁就執行以上代碼,這樣會加快執行速度
end

else
begin
--以下代碼賦予了@strSQL以真正執行的SQL代碼
set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from ['
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['+ @fldName + '] from [' + @tblName + ']' + @strOrder + ') as tblTmp)'+ @strOrder
if @strWhere != ''
set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ ' from ['
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['
+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['
+ @fldName + '] from [' + @tblName + '] where ' + @strWhere + ' '
+ @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
end
end
exec SP_EXECUTESQL @strSQL

--以下代碼可取得總頁數
set @doCount=@@rowcount
GO

一個比較實用的大資料量分頁 Store Procedure

create proc sp_PublicTurnPageWebSite(
@TBName nvarchar(100)='', --表名,如 pinyin
@PageSize int=10, --每頁的記錄數,默認爲 10
@CurPage int=1, --表示當前頁 1
@KeyField nvarchar(100)='ID', --關鍵字段名,默認爲 ID,該欄位要求是表中的索引 或 無重復和不爲空的欄位
@KeyAscDesc nvarchar(4)='ASC', --關鍵字的升、降冪,默認爲昇冪 ASC , 降冪爲 DESC
@Fields nvarchar(500)='*', --所選擇的列名,默認爲全選
@Condition nvarchar(200)='', --where 條件,默認爲空
@Order nvarchar(200)='' --排序條件,默認爲空
) with encryption as
if @TBName = ''
begin
raiserror('請指定表名!',11,1)
return
end
if @PageSize <=0 or @CurPage <0
begin
raiserror('當前頁數和每頁的記錄數都必須大於零!',11,1)
return
end
if @KeyAscDesc = 'DESC'
set @KeyAscDesc = '<'
else
set @KeyAscDesc = '>'
if @Condition <> ''
set @Condition = ' where ' + @Condition
declare @SQL nvarchar(2000)

set @SQL = ''
if @CurPage = 1
set @SQL = @SQL + 'SELECT Top ' + cast(@PageSize as nvarchar(20)) + ' ' + @Fields + ' FROM ' + @TBName + @Condition + ' ' + @Order
else
begin
declare @iTopNum int
set @iTopNum = @PageSize * (@CurPage - 1)
set @SQL = @SQL + 'declare @sLastValue nvarchar(100)' + char(13)
set @SQL = @SQL + 'SELECT Top ' + cast(@iTopNum as nvarchar(20)) + ' @sLastValue=' + @KeyField + ' FROM ' + @TBName + @Condition + ' ' + @Order + char(13)

declare @Condition2 nvarchar(200)
if @Condition = ''
set @Condition2 = ' where ' + @KeyField + @KeyAscDesc + '@sLastValue '
else
set @Condition2 = ' and ' + @KeyField + @KeyAscDesc + '@sLastValue '
set @SQL = @SQL + 'SELECT Top ' + cast(@PageSize as nvarchar(20)) + ' ' + @Fields + ' FROM ' + @TBName + @Condition + @Condition2 + @Order
end
EXECUTE sp_executesql @SQL

在 SQL 中, 想顯示不足五位時補 0 的作法


declare @num int
set @num=12

select right(100000+@num,5)

SQL語句導入導出大全

/******* 導出到Excel
EXEC master..xp_cmdshell ’bcp SettleDB.dbo.shanghu out c:\temp1.xls -c -q -S"GNETDATA/GNETDATA" -U"sa" -P""’

/*********** 導入Excel
SELECT *
FROM OpenDataSource( ’Microsoft.Jet.OLEDB.4.0’,
’Data Source="c:\test.xls";User ID=Admin;Password=;Extended properties=Excel 5.0’)...xactions


SELECT cast(cast(科目編號 as numeric(10,2)) as nvarchar(255))+’ ’ 轉換後的別名
FROM OpenDataSource( ’Microsoft.Jet.OLEDB.4.0’,
’Data Source="c:\test.xls";User ID=Admin;Password=;Extended properties=Excel 5.0’)...xactions

/** 導入文字檔案
EXEC master..xp_cmdshell ’bcp "dbname..tablename" in c:\DT.txt -c -Sservername -Usa -Ppassword’

/** 導出文字檔案
EXEC master..xp_cmdshell ’bcp "dbname..tablename" out c:\DT.txt -c -Sservername -Usa -Ppassword’

EXEC master..xp_cmdshell ’bcp "Select * from dbname..tablename" queryout c:\DT.txt -c -Sservername -Usa -Ppassword’

導出到TXT文本,用逗號分開
exec master..xp_cmdshell ’bcp "庫名..表名" out "d:\tt.txt" -c -t ,-U sa -P password’


BULK INSERT 庫名..表名
FROM ’c:\test.txt’
WITH (
FIELDTERMINATOR = ’;’,
ROWTERMINATOR = ’\n’
)


--/* dBase IV文件
select * from
OPENROWSET(’MICROSOFT.JET.OLEDB.4.0’
,’dBase IV;HDR=NO;IMEX=2;DATABASE=C:\’,’select * from [客戶資料4.dbf]’)
--*/

--/* dBase III文件
select * from
OPENROWSET(’MICROSOFT.JET.OLEDB.4.0’
,’dBase III;HDR=NO;IMEX=2;DATABASE=C:\’,’select * from [客戶資料3.dbf]’)
--*/

--/* FoxPro 資料庫
select * from openrowset(’MSDASQL’,
’Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\’,
’select * from [aa.DBF]’)
--*/

/**************導入DBF文件****************/
select * from openrowset(’MSDASQL’,
’Driver=Microsoft Visual FoxPro Driver;
SourceDB=e:\VFP98\data;
SourceType=DBF’,
’select * from customer where country != "USA" order by country’)
go
/***************** 導出到DBF ***************/
如果要導出資料到已經生成結構(即現存的)FOXPRO表中,可以直接用下面的SQL語句

insert into openrowset(’MSDASQL’,
’Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\’,
’select * from [aa.DBF]’)
select * from 表

說明:
SourceDB=c:\ 指定foxpro表所在的文件夾
aa.DBF 指定foxpro表的檔案名.




/*************導出到Access********************/
insert into openrowset(’Microsoft.Jet.OLEDB.4.0’,
’x:\A.mdb’;’admin’;’’,A表) select * from 資料庫名..B表

/*************導入Access********************/
insert into B表 selet * from openrowset(’Microsoft.Jet.OLEDB.4.0’,
’x:\A.mdb’;’admin’;’’,A表)

********************* 導入 xml 文件

DECLARE @idoc int
DECLARE @doc varchar(1000)
--sample XML document
SET @doc =’



Customer was very satisfied




Important
Happy Customer.





-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc

-- Execute a SELECT statement using OPENXML rowset provider.
SELECT *
FROM OPENXML (@idoc, ’/root/Customer/Order’, 1)
WITH (oid char(5),
amount float,
comment ntext ’text()’)
EXEC sp_xml_removedocument @idoc


/********************導整個資料庫*********************************************/

用bcp實現的存儲過程


/*
實現資料導入/導出的存儲過程
根據不同的參數,可以實現導入/導出整個資料庫/單個表
調用示例:
--導出調用示例
----導出單個表
exec file2table ’zj’,’’,’’,’xzkh_sa..地區資料’,’c:\zj.txt’,1
----導出整個資料庫
exec file2table ’zj’,’’,’’,’xzkh_sa’,’C:\docman’,1

--導入調用示例
----導入單個表
exec file2table ’zj’,’’,’’,’xzkh_sa..地區資料’,’c:\zj.txt’,0
----導入整個資料庫
exec file2table ’zj’,’’,’’,’xzkh_sa’,’C:\docman’,0

*/
if exists(select 1 from sysobjects where name=’File2Table’ and objectproperty(id,’IsProcedure’)=1)
drop procedure File2Table
go
create procedure File2Table
@servername varchar(200) --伺服器名
,@username varchar(200) --用戶名,如果用NT驗證方式,則爲空’’
,@password varchar(200) --密碼
,@tbname varchar(500) --資料庫.dbo.表名,如果不指定:.dbo.表名,則導出資料庫的所有用戶表
,@filename varchar(1000) --導入/導出路徑/檔案名,如果@tbname參數指明是導出整個資料庫,則這個參數是文件存放路徑,檔案名自動用表名.txt
,@isout bit --1爲導出,0爲導入
as
declare @sql varchar(8000)

if @tbname like ’%.%.%’ --如果指定了表名,則直接導出單個表
begin
set @sql=’bcp ’+@tbname
+case when @isout=1 then ’ out ’ else ’ in ’ end
+’ "’+@filename+’" /w’
+’ /S ’+@servername
+case when isnull(@username,’’)=’’ then ’’ else ’ /U ’+@username end
+’ /P ’+isnull(@password,’’)
exec master..xp_cmdshell @sql
end
else
begin --導出整個資料庫,定義游標,取出所有的用戶表
declare @m_tbname varchar(250)
if right(@filename,1)<>’\’ set @filename=@filename+’\’

set @m_tbname=’declare #tb cursor for select name from ’+@tbname+’..sysobjects where xtype=’’U’’’
exec(@m_tbname)
open #tb
fetch next from #tb into @m_tbname
while @@fetch_status=0
begin
set @sql=’bcp ’+@tbname+’..’+@m_tbname
+case when @isout=1 then ’ out ’ else ’ in ’ end
+’ "’+@filename+@m_tbname+’.txt " /w’
+’ /S ’+@servername
+case when isnull(@username,’’)=’’ then ’’ else ’ /U ’+@username end
+’ /P ’+isnull(@password,’’)
exec master..xp_cmdshell @sql
fetch next from #tb into @m_tbname
end
close #tb
deallocate #tb
end
go


/**********************Excel導到Txt****************************************/
想用
select * into opendatasource(...) from opendatasource(...)
實現將一個Excel文件內容導入到一個文字檔案

假設Excel中有兩列,第一列爲姓名,第二列爲很行帳號(16位)
且銀行帳號導出到文字檔案後分兩部分,前8位元和後8位分開。


如果要用你上面的語句插入的話,文字檔案必須存在,而且有一行:姓名,銀行賬號1,銀行賬號2
然後就可以用下面的語句進行插入
注意檔案名和目錄根據你的實際情況進行修改.

insert into
opendatasource(’MICROSOFT.JET.OLEDB.4.0’
,’Text;HDR=Yes;DATABASE=C:\’
)...[aa#txt]
--,aa#txt)
--*/
select 姓名,銀行賬號1=left(銀行賬號,8),銀行賬號2=right(銀行賬號,8)
from
opendatasource(’MICROSOFT.JET.OLEDB.4.0’
,’Excel 5.0;HDR=YES;IMEX=2;DATABASE=c:\a.xls’
--,Sheet1$)
)...[Sheet1$]

如果你想直接插入並生成文字檔案,就要用bcp

declare @sql varchar(8000),@tbname varchar(50)

--首先將excel表內容導入到一個全局臨時表
select @tbname=’[##temp’+cast(newid() as varchar(40))+’]’
,@sql=’select 姓名,銀行賬號1=left(銀行賬號,8),銀行賬號2=right(銀行賬號,8)
into ’+@tbname+’ from
opendatasource(’’MICROSOFT.JET.OLEDB.4.0’’
,’’Excel 5.0;HDR=YES;IMEX=2;DATABASE=c:\a.xls’’
)...[Sheet1$]’
exec(@sql)

--然後用bcp從全局臨時表導出到文字檔案
set @sql=’bcp "’+@tbname+’" out "c:\aa.txt" /S"(local)" /P"" /c’
exec master..xp_cmdshell @sql

--刪除臨時表
exec(’drop table ’+@tbname)


用bcp將文件導入導出到資料庫的存儲過程:


/*--bcp-二進位文件的導入導出

支援image,text,ntext欄位的導入/導出
image適合於二進位文件;text,ntext適合於文本資料檔案

注意:導入時,將覆蓋滿足條件的所有行
導出時,將把所有滿足條件的行也出到指定文件中

此存儲過程僅用bcp實現
鄒建 2003.08-----------------*/

/*--調用示例
--資料導出
exec p_binaryIO ’zj’,’’,’’,’acc_演示資料..tb’,’img’,’c:\zj1.dat’

--資料導出
exec p_binaryIO ’zj’,’’,’’,’acc_演示資料..tb’,’img’,’c:\zj1.dat’,’’,0
--*/
if exists (select * from dbo.sysobjects where id = object_id(N’[dbo].[p_binaryIO]’) and OBJECTPROPERTY(id, N’IsProcedure’) = 1)
drop procedure [dbo].[p_binaryIO]
GO

Create proc p_binaryIO
@servename varchar (30),--伺服器名稱
@username varchar (30), --用戶名
@password varchar (30), --密碼
@tbname varchar (500), --資料庫..表名
@fdname varchar (30), --欄位名
@fname varchar (1000), --目錄+檔案名,處理過程中要使用/覆蓋:@filename+.bak
@tj varchar (1000)=’’, --處理條件.對於資料導入,如果條件中包含@fdname,請指定表名字首
@isout bit=1 --1導出((默認),0導入
AS
declare @fname_in varchar(1000) --bcp處理應答檔案名
,@fsize varchar(20) --要處理的文件的大小
,@m_tbname varchar(50) --臨時表名
,@sql varchar(8000)

--則取得導入文件的大小
if @isout=1
set @fsize=’0’
else
begin
create table #tb(可選名 varchar(20),大小 int
,創建日期 varchar(10),創建時間 varchar(20)
,上次寫操作日期 varchar(10),上次寫操作時間 varchar(20)
,上次訪問日期 varchar(10),上次訪問時間 varchar(20),特性 int)
insert into #tb
exec master..xp_getfiledetails @fname
select @fsize=大小 from #tb
drop table #tb
if @fsize is null
begin
print ’文件未找到’
return
end

end

--生成資料處理應答文件
set @m_tbname=’[##temp’+cast(newid() as varchar(40))+’]’
set @sql=’select * into ’+@m_tbname+’ from(
select null as 類型
union all select 0 as 字首
union all select ’+@fsize+’ as 長度
union all select null as 結束
union all select null as 格式
) a’
exec(@sql)
select @fname_in=@fname+’_temp’
,@sql=’bcp "’+@m_tbname+’" out "’+@fname_in
+’" /S"’+@servename
+case when isnull(@username,’’)=’’ then ’’
else ’" /U"’+@username end
+’" /P"’+isnull(@password,’’)+’" /c’
exec master..xp_cmdshell @sql
--刪除臨時表
set @sql=’drop table ’+@m_tbname
exec(@sql)

if @isout=1
begin
set @sql=’bcp "select top 1 ’+@fdname+’ from ’
+@tbname+case isnull(@tj,’’) when ’’ then ’’
else ’ where ’+@tj end
+’" queryout "’+@fname
+’" /S"’+@servename
+case when isnull(@username,’’)=’’ then ’’
else ’" /U"’+@username end
+’" /P"’+isnull(@password,’’)
+’" /i"’+@fname_in+’"’
exec master..xp_cmdshell @sql
end
else
begin
--爲資料導入準備臨時表
set @sql=’select top 0 ’+@fdname+’ into ’
+@m_tbname+’ from ’ +@tbname
exec(@sql)

--將資料導入到臨時表
set @sql=’bcp "’+@m_tbname+’" in "’+@fname
+’" /S"’+@servename
+case when isnull(@username,’’)=’’ then ’’
else ’" /U"’+@username end
+’" /P"’+isnull(@password,’’)
+’" /i"’+@fname_in+’"’
exec master..xp_cmdshell @sql

--將資料導入到正式表中
set @sql=’update ’+@tbname
+’ set ’+@fdname+’=b.’+@fdname
+’ from ’+@tbname+’ a,’
+@m_tbname+’ b’
+case isnull(@tj,’’) when ’’ then ’’
else ’ where ’+@tj end
exec(@sql)

--刪除資料處理臨時表
set @sql=’drop table ’+@m_tbname
end

--刪除資料處理應答文件
set @sql=’del ’+@fname_in
exec master..xp_cmdshell @sql

go


/** 導入文字檔案
EXEC master..xp_cmdshell ’bcp "dbname..tablename" in c:\DT.txt -c -Sservername -Usa -Ppassword’

改爲如下,不需引號
EXEC master..xp_cmdshell ’bcp dbname..tablename in c:\DT.txt -c -Sservername -Usa -Ppassword’

/** 導出文字檔案
EXEC master..xp_cmdshell ’bcp "dbname..tablename" out c:\DT.txt -c -Sservername -Usa -Ppassword’
此句需加引號

SqlServer資料庫的備份和恢復措施

一、備份資料庫

1、打開SQL企業管理器,在控制臺根目錄中依次點開Microsoft SQL Server
2、SQL Server組-->雙擊打開你的伺服器-->雙擊打開資料庫目錄
3、選擇你的資料庫名稱(如論壇資料庫Forum)-->然後點上面功能表中的工具-->選擇備份資料庫
4、備份選項選擇完全備份,目的中的備份到如果原來有路徑和名稱則選中名稱點刪除,然後點添加,如果原來沒有路徑和名稱則直接選擇添加,接著指定路徑和檔案名,指定後點確定返回備份視窗,接著點確定進行備份

二、還原資料庫

1、打開SQL企業管理器,在控制臺根目錄中依次點開Microsoft SQL Server
2、SQL Server組-->雙擊打開你的伺服器-->點圖示欄的新建資料庫圖示,新建資料庫的名字自行取
3、點擊新建好的資料庫名稱(如論壇資料庫Forum)-->然後點上面功能表中的工具-->選擇恢復資料庫
4、在彈出來的視窗中的還原選項中選擇從設備-->點選擇設備-->點添加-->然後選擇你的備份檔案名-->添加後點確定返回,這時候設備欄應該出現您剛才選擇的資料庫備份檔案名,備份號默認爲1(如果您對同一個文件做過多次備份,可以點擊備份號旁邊的查看內容,在核取方塊中選擇最新的一次備份後點確定)-->然後點擊上方常規旁邊的選項按鈕
5、在出現的視窗中選擇在現有資料庫上強制還原,以及在恢復完成狀態中選擇使資料庫可以繼續運行但無法還原其他事務日誌的選項。在視窗的中間部位的將資料庫文件還原爲這裏要按照你SQL的安裝進行設置(也可以指定自己的目錄),邏輯檔案名不需要改動,移至物理檔案名要根據你所恢復的機器情況做改動,如您的SQL資料庫裝在D:\Program Files\Microsoft SQL Server\MSSQL\Data,那麽就按照您恢復機器的目錄進行相關改動改動,並且最後的檔案名最好改成您當前的資料庫名(如原來是bbs_data.mdf,現在的資料庫是forum,就改成forum_data.mdf),日誌和資料檔案都要按照這樣的方式做相關的改動(日誌的檔案名是*_log.ldf結尾的),這裏的恢復目錄您可以自由設置,前提是該目錄必須存在(如您可以指定d: qldata\bbs_data.mdf或者d: qldata\bbs_log.ldf),否則恢復將報錯
6、修改完成後,點擊下面的確定進行恢復,這時會出現一個進度條,提示恢復的進度,恢復完成後系統會自動提示成功,如中間提示報錯,請記錄下相關的錯誤內容並詢問對SQL操作比較熟悉的人員,一般的錯誤無非是目錄錯誤或者檔案名重復或者檔案名錯誤或者空間不夠或者資料庫正在使用中的錯誤,資料庫正在使用的錯誤您可以嘗試關閉所有關於SQL視窗然後重新打開進行恢復操作,如果還提示正在使用的錯誤可以將SQL服務停止然後重起看看,至於上述其他的錯誤一般都能按照錯誤內容做相應改動後即可恢復

三、收縮資料庫

一般情況下,SQL資料庫的收縮並不能很大程度上減小資料庫大小,其主要作用是收縮日誌大小,應當定期進行此操作以免資料庫日誌過大
1、設置資料庫模式爲簡單模式:打開SQL企業管理器,在控制臺根目錄中依次點開Microsoft SQL Server-->SQL Server組-->雙擊打開你的伺服器-->雙擊打開資料庫目錄-->選擇你的資料庫名稱(如論壇資料庫Forum)-->然後點擊右鍵選擇屬性-->選擇選項-->在故障還原的模式中選擇“簡單”,然後按確定保存
2、在當前資料庫上點右鍵,看所有任務中的收縮資料庫,一般裏面的默認設置不用調整,直接點確定
3、收縮資料庫完成後,建議將您的數據庫屬性重新設置爲標準模式,操作方法同第一點,因爲日誌在一些異常情況下往往是恢復資料庫的重要依據

四、設定每日自動備份資料庫

強烈建議有條件的用戶進行此操作!
1、打開企業管理器,在控制臺根目錄中依次點開Microsoft SQL Server-->SQL Server組-->雙擊打開你的伺服器
2、然後點上面功能表中的工具-->選擇資料庫維護計劃器
3、下一步選擇要進行自動備份的資料-->下一步更新資料優化資訊,這裏一般不用做選擇-->下一步檢查資料完整性,也一般不選擇
4、下一步指定資料庫維護計劃,默認的是1周備份一次,點擊更改選擇每天備份後點確定
5、下一步指定備份的磁片目錄,選擇指定目錄,如您可以在D盤新建一個目錄如:d:\databak,然後在這裏選擇使用此目錄,如果您的資料庫比較多最好選擇爲每個資料庫建立子目錄,然後選擇刪除早於多少天前的備份,一般設定4-7天,這看您的具體備份要求,備份檔案副檔名一般都是bak就用默認的
6、下一步指定事務日誌備份計劃,看您的需要做選擇-->下一步要生成的報表,一般不做選擇-->下一步維護計劃歷史記錄,最好用默認的選項-->下一步完成
7、完成後系統很可能會提示Sql Server Agent服務未啓動,先點確定完成計劃設定,然後找到桌面最右邊狀態欄中的SQL綠色圖示,雙擊點開,在服務中選擇Sql Server Agent,然後點擊運行箭頭,選上下方的當啓動OS時自動啓動服務
8、這個時候資料庫計劃已經成功的運行了,他將按照您上面的設置進行自動備份

修改計劃:
1、打開企業管理器,在控制臺根目錄中依次點開Microsoft SQL Server-->SQL Server組-->雙擊打開你的伺服器-->管理-->資料庫維護計劃-->打開後可看到你設定的計劃,可以進行修改或者刪除操作

五、資料的轉移(新建資料庫或轉移伺服器)

一般情況下,最好使用備份和還原操作來進行轉移資料,在特殊情況下,可以用導入導出的方式進行轉移,這裏介紹的就是導入導出方式,導入導出方式轉移資料一個作用就是可以在收縮資料庫無效的情況下用來減小(收縮)資料庫的大小,本操作默認爲您對SQL的操作有一定的瞭解,如果對其中的部分操作不理解,可以諮詢動網相關人員或者查詢網上資料
1、將原資料庫的所有表、存儲過程導出成一個SQL文件,導出的時候注意在選項中選擇編寫索引腳本和編寫主鍵、外鍵、預設值和檢查約束腳本選項
2、新建資料庫,對新建資料庫執行第一步中所建立的SQL文件
3、用SQL的導入導出方式,對新資料庫導入原資料庫中的所有表內容

使用 Microsoft SQL Server 2000 的全文搜索功能構建 Web 搜索應用程式

Andrew B. Cencini Microsoft Corporation 2002年12月
適用於: Microsoft® SQL™ Server 2000摘要:學習如何充分利用 SQL Server 2000 的全文搜索功能。
本文包含有關實現最大吞吐率和最佳性能的幾點提示和技巧。
目錄簡介
全文搜索功能簡介
配置全文搜索功能
全文查詢
排位元和優化
其他性能技巧
小結
附錄 A:實現全文搜索功能的最佳選擇
附錄 B:使用最佳選擇、結果分頁和有效全文查詢邏輯的示例應用程式
附錄 C:資源

簡介
使用 Microsoft® SQL™ Server 2000 的全文搜索功能,可以對在非結構化文本資料上生成的索引執行快速、靈活的查詢。常用的全文搜索工具是網站的搜索引擎。爲了幫助讀者理解全文搜索功能的最佳使用方法,本文介紹了大量抽象概念;並對優化全文索引和查詢以實現最大吞吐率和最佳性能,提供了幾點提示和技巧。全文搜索功能簡介全文搜索功能在 SQL Server 7.0 中引入。全文搜索的核心引擎建立在 Microsoft Search (MSSearch) 技術上,Microsoft Exchange 和 Microsoft SharePoint™ Portal Server 等産品中也採用了此項技術。SQL Server 7.0 全文搜索中公開的功能可提供基本的文本搜索功能,並使用早期版本的 MSSearch;而 SQL Server 2000 的全文搜索實現則包含一組可靠的索引和查詢功能,並在 SQL Server 7.0 的基礎之上添加了幾項增強功能。這些增強功能包括:通過 Microsoft 群集服務完全支援群集操作,能夠過濾和索引 IMAGE 列中存儲的文檔,提供改進的語言支援,以及在性能、可縮放性和可靠性方面進行了改進。MSSearch 生成、維護和查詢文件系統中(而不是 SQL Server 中)存儲的全文索引。MSSearch 進行全文索引時使用的邏輯和物理存儲單元是目錄。全文目錄在每個資料庫中包含一個或多個全文索引 - 可以爲 SQL Server 中的每個表創建一個全文索引,且索引中可以包含該表中的一列或多列。每個表只能屬於一個目錄,且每個表只能創建一個索引。我們將簡單介紹有關組織全文目錄和索引的最佳方案 - 但首先,讓我們來簡單瞭解一下全文搜索的工作原理。配置全文搜索功能要爲 SQL Server 中存儲的文本資料創建全文索引,應該先完成以下幾步準備工作。第一步是以全文方式啓用包含要生成索引的文本資料的資料庫(如果您尚未執行此操作)。注意:執行以下語句將丟棄並重新創建屬於要啓用全文搜索的資料庫的所有全文目錄。除非要重新創建全文目錄,否則請確保在要啓用的特定資料庫中未創建任何全文目錄。如果您是 sysadmin 角色的成員或此資料庫的 db_owner,可以繼續進行並發出以下語句:
use Northwind exec sp_fulltext_database 'enable'

接下來,您需要創建全文目錄,以存儲全文索引。正如前面所提到的,此目錄中的資料存儲在文件系統中(而不是 SQL Server 中),因此,在考慮全文目錄的存儲位置時應該仔細選擇。除非指定其他位置,否則全文目錄將存儲在 FTDATA 目錄(位於 Microsoft SQL Server\MSSQL 存儲位置中)的子目錄中。以下是在非默認位置創建全文目錄的方法:
exec sp_fulltext_catalog 'Cat_Desc', 'create', 'f:\ft'

在本例中,全文目錄將創建爲“f:\ft”的子目錄,如果您查看文件系統的該部分,將看到它有了自己的目錄。MSSearch 使用的全文目錄的命名規則是:[color=Blue]SQL+dbid+catalogID[/color]

目錄 ID 從 00005 開始,並且每新建一個目錄就遞增 1。如果可能的話,最好在其所在的物理驅動器上創建全文目錄。如果生成全文索引的進程需要進行大量的 I/O 操作(具體而言,就是從 SQL Server 中讀取資料,然後向文件系統寫入索引),則應避免使 I/O 子系統成爲瓶頸。那麽,全文目錄有多大呢?通常情況下,全文目錄的系統開銷比 SQL Server 中存儲的資料(對其進行全文索引)量高出大約 30%;但是,此規則取決於資料中唯一單詞(或主鍵)的分佈,以及被您視爲是干擾詞的單詞的分佈。干擾詞(或終止詞)是指要排除在全文索引和查詢以外的詞語(因爲它們不是您感興趣的搜索詞,而且出現頻率很高,所以只會使索引變得很大,而不會有實際效果)。稍後,我們將介紹有關干擾詞選擇方面的注意事項,以及如何優化干擾詞以改善查詢性能。如果您尚未執行此操作,請在每個要生成全文索引的表上創建一個唯一的單列非空索引。這個唯一索引用於將表中的每一行映射到 MSSearch 內部使用的一個唯一可壓縮主鍵。接下來,您需要讓 MSSearch 知道您要爲表創建全文索引。對表發出以下語句可將該表添加到所選的全文目錄中(在本例中,它是我們在前面創建的“Cat_Desc”):
exec sp_fulltext_table 'Categories', 'create', 'Cat_Desc', 'PK_Categories'

下一步是向此全文索引添加列。您可以爲每一列選擇一種語言,如果該列的類型爲 IMAGE,則必須再指定一列,以指示 IMAGE 列的每一行中存儲的文檔類型。在列語言選擇方面,有一些重要但尚未成文的注意事項。這些注意事項與文本的標記方式以及 MSSearch 對文本的索引方式有關。被索引的文本是通過一個稱作單詞分隔符號(用作單詞邊界標記)的元件提供的。在英文中,單詞分隔符號通常是空格或某種形式的標點符號;而在其他語言中(例如德語),單詞或字元可以組合在一起;因此,所選的列語言應表示要存儲在該列的行中的語言。如果不確定,最好的方法通常是使用中性單詞分隔符號(只使用空格和標點符號執行標記功能)。選擇列語言的另一個好處是“尋根溯源”。全文查詢中的尋根溯源是指在特定語言中搜索某一單詞的所有變化形式的過程。選擇語言的另一個考慮因素與資料的表示方法有關。對於非 IMAGE 列資料來說,不需要執行特殊的過濾操作;而文本通常需要將單詞分隔元件按原樣傳遞。單詞分隔符號主要用於處理書面文本。因此,如果文本中有任何類型的標記(例如 HTML),則在索引和搜索過程中,語言精確性將不會很高。這種情況下,您有兩種選擇 - 首選方法是只將文本資料存儲在 IMAGE 列中,並指明其文檔類型,以便對其進行過濾。如果不選擇此方法,則可以考慮使用中性單詞分隔符號,並且可能的話,在干擾詞列表中添加標記資料(例如 HTML 中的“br”)。在指定了中性語言的列中不能進行任何基於語言的尋根溯源,但有些環境可能會要求您選擇此方法。在知道列選項後,通過發出以下語句在全文索引中添加一列或兩列:
exec sp_fulltext_column 'Categories', 'Description', 'add'

您可能注意到,此處未指定任何語言 - 這種情況下,將使用默認的全文語言。可以通過系統存儲過程“sp_configure”爲伺服器設置默認全文語言。將所有列添加到全文索引後,即可執行填充操作。填充方法之多實在是不勝枚舉,此處不作詳細介紹。在本例中,只需對表啓動完全填充,並等待它執行完畢:
exec sp_fulltext_table 'Categories', 'start_full'

您可能希望使用 FULLTEXTCATALOGPROPERTY 或 OBJECTPROPERTY 函數來監視填充狀態。要獲取目錄填充狀態,可以執行:
select FULLTEXTCATALOGPROPERTY('Cat_Desc', 'Populatestatus')

通常情況下,如果完全填充正在進行,則返回的結果是“1”。

有關如何使用 FULLTEXTCATALOGPROPERTY 和 OBJECTPROPERTY 的詳細資訊,請參閱 SQL Server Books Online。

全文查詢查詢全文索引與執行 SQL Server 中的標準關聯式查詢略有不同。由於索引是在 SQL Server 外部進行存儲和管理的,因此全文查詢處理大部分由 MSSearch 完成(因此,那些一部分是關聯式、一部分基於全文的查詢將被單獨處理),這樣做有時會損害性能。從本質上說,執行全文查詢時,查詢詞傳遞給 MSSearch,後者遍曆其內部資料結構(索引),並向 SQL Server 返回主鍵和排位值。如果執行 CONTAINS 或 FREETEXT 查詢,則通常看不到主鍵或排位值,但如果執行 CONTAINSTABLE 或 FREETEXTTABLE 查詢,則將獲得這些值,然後這些值通常會與基表合併在一起。與基表合併主鍵的進程需要很高的系統開銷 - 稍後,我們將向您介紹一些巧妙的方法以儘量減少或完全避免這種合併。如果您通過不斷思考,對全文查詢如何返回資料有了一個初步瞭解,就可以推測出 CONTAINS/FREETEXT 查詢僅執行 CONTAINSTABLE/FREETEXTTABLE 查詢並與基表進行合併。有了這樣的瞭解,您應該避免使用這些類型的查詢,除非不這樣做的開銷更高。在 Web 搜索應用程式中,使用 CONTAINSTABLE 與 FREETEXTTABLE 比使用不帶 TABLE 的同類函數好得多。

到現在爲止,您已經知道全文查詢是用來從 SQL Server 之外存儲的 MSSearch 索引中訪問資料的特殊方法,還知道如果盲目地與基表進行合併,就會遇到麻煩。應該瞭解的另外一個重要內容是 CONTAINS 樣式查詢與 FREETEXT 樣式查詢之間的本質差別。CONTAINS 查詢用於對所查詢的所有詞語執行完全匹配查詢。無論您只查找單個單詞,還是查找以“orange”開頭的所有單詞,系統只返回包含所有搜索詞的結果。因此,CONTAINS 查詢速度很快,因爲它們通常返回很少的結果,並且不需要執行過多的附加處理。CONTAINS 查詢的缺點包括令人生厭的干擾詞過濾問題。經驗豐富的開發人員以及過去使用過全文搜索的資料庫管理員,在試圖匹配只包含單個干擾詞的單詞或片語時,曾遇到過“您的查詢只包含干擾詞”這樣令人吃驚的錯誤。要避免收到此錯誤,方法之一是在執行全文查詢之前過濾出干擾詞。向包含干擾詞的 CONTAINS 查詢返回結果是不可能的,因爲此類查詢只返回與整個查詢字串完全匹配的結果。由於干擾詞不是全文索引項,因此包含干擾詞的 CONTAINS 查詢不會返回任何行。FREETEXT 查詢消除了 CONTAINS 查詢中偶爾出現的所有警告說明。當發出 FREETEXT 查詢時,實際上發出的是詞根查詢。因此,當您搜索“root beer”時,“root”和“beer”包含其所有形式(尋根溯源與語言相關;所用的語言由生成索引時指定的全文列語言確定,並且在所有查詢的列中必須相同),並且系統將返回至少與這些詞語之一匹配的所有行。FREETEXT 查詢的負面影響是它們通常比 CONTAINS 查詢耗用更多的 CPU - 因爲要尋根溯源以及返回更多的結果,就需要包含更複雜的排位計算。不過,基於 FREETEXT 的查詢非常靈活,而且速度非常快,是基於 Web 的搜索應用程式中通常使用的最佳選擇。排位和優化我經常遇到使用全文搜索的用戶,他們問我排位編號是什麽意思,以及如何將排位編號轉換成某種用戶可以理解的值。對這個問題,回答可長可短,在這裏我將進行簡要回答。

簡單而言,這些排位編號不如結果返回的順序那樣重要。也就是說,當您按照排位對結果進行排序時,總是首先返回關聯程度最高的結果。排位值本身常常變化 - 全文搜索使用概率排位元演算法,即返回的每個文檔的關聯性受全文索引中的任何或所有其他文檔的直接影響。有些人認爲,一種有助於增加某些行排位的技巧是在這些行的全文索引列中重復常用的搜索關鍵字。儘管在某種程度上,這種方法可能會提高這些行因某些關鍵字而首先返回的幾率,但在其他情況下,可能會適得其反 - 而且還存在使詞語查詢性能降低的風險。較好的解決方案是爲搜索應用程式實現“最佳選擇”系統(請參閱以下示例),這樣就可以確保首先返回某些文檔。多次重復使用關鍵字會使這些特定關鍵字的全文索引擴大,並使得 MSSearch 在查找正確行和計算排位時浪費時間。如果全文索引資料量很大,並嘗試使用了此方法,您可能會發現某些全文查詢很耗時。如果能夠實現更細緻(也可能更精確)的“最佳選擇”系統,您會發現它明顯改善了查詢性能。多次重復資料的另一個問題與用於組合關聯式查詢和全文查詢的常用技巧有關。許多使用全文搜索的用戶都深受此問題的困擾,每當他們試圖將某種篩檢程式應用于全文查詢返回的結果時,便會遇到這樣的問題。正如前面所說的,全文查詢爲每個匹配行返回一個主鍵和一個排位 - 要收集有關這些行的任何詳細資訊,必須與它的基表進行合併。由於從無限制的全文查詢中可能會返回任意數量的結果,因此合併可能需要大量系統開銷。人們發現避免合併的一個有效方法是只在全文索引中添加要過濾的資料(如果可能)。換句話說,如果用戶要從報紙上所有文章的正文中搜索關鍵字“Ichiro”,並且只希望返回該報上體育專欄中的文章,則查詢語句通常如下所示:

-- [方法 1:]-- 開銷最高:先全部選擇,然後再合併和過濾SELECT ARTICLES_TBL.Author, ARTICLES_TBL.Body, ARTICLES_TBL.Dateline, FT_TBL.[rank] FROM FREETEXTTABLE(Articles, Body, 'Ichiro') AS FT_TBLINNER JOIN Articles AS ARTICLES_TBLON FT_TBL.[key] = ARTICLES_TBL.ArticleIDWHERE ARTICLES_TBL.Category = 'Sports'

-- [方法 2:]-- 可以使用,但會導致意外結果並變慢,或者會返回不準確的結果: -- 執行全文過濾,並且只提取主鍵和排位-- (處理在 Web 伺服器上完成)SELECT [key], [rank] FROM CONTAINSTABLE(Articles, *, 'FORMSOF(INFLECTIONAL('Ichiro') AND "sports"')


這兩個查詢要麽不必要地佔用大量系統開銷,要麽存在返回錯誤結果的可能性(在第二個查詢中,“sports”很可能出現在所有類型的文章中)。這兩項技術還存在其他變體,但這是兩種非常簡單的模型。如果可行,我通常建議您對資料進行水平劃分。即,“類別”列的每個可能值都自成一列(或表),並且與該文章相關的可搜索關鍵字僅存儲在此列中。採用此方法,而不是使用一個“正文”列和一個“類別”列,可以去掉“類別”列,而使用存儲可搜索關鍵字的“Body_”列。如以下示例所示:-- 如果您可以調整架構,這非常有效 ‐ 每個類別-- 都成爲自己的列(或表格),並且需要命中的-- 全文索引也較少。這明顯需要作一些解釋……
SELECT [key], [rank] FROM FREETEXTTABLE(Articles, Body_Sports, 'Ichiro')

對於包含大量資料,且這些資料可適應此架構(或許是主架構)更改的系統,其性能會得到顯著的提高。但在何時應用多個篩檢程式或不應用篩檢程式方面卻有著明顯的限制。當然,還有其他的方法可以解決這些問題。通過以上示例,您會瞭解一種將某些搜索條件抽象到架構的方法 - 實際上是“欺騙”優化程式(更確切的說是“成爲”優化程式),因爲在 SQL Server 本身的全文查詢中當前不存在本地優化。其他性能技巧人們在聊天時常常問我的另一個問題是如何才能分頁顯示全文查詢結果。換句話說,如果我要發出“root beer”查詢,一次在某一 Web 頁上顯示 40 個結果,並且只希望返回該頁面上的 40 個結果(例如,如果我在第三頁,我希望僅返回第 81 至第 120 條結果)。對於分頁顯示結果,我曾見過多種方法,但沒有一種方法能夠做到百分之百有效。我所推薦的方法可以最大程度地減少全文查詢執行的次數(實際上,對於要分頁顯示的每個結果集只需執行一次),並將 Web 伺服器用作一個簡單的緩存。從更高的層面來講,您只需在全文查詢中檢索一個完整的主鍵和排位元值行集合(如果需要,可以在架構中使用最佳選擇並提取常用篩檢程式),並將其存儲在 Web 伺服器的記憶體中(這取決於您的應用程式和負載,想象將 <32 位元組的典型主鍵大小與 <4 位元組的排位元大小相加 [等於 <36 位元組],然後乘以通常返回的結果集 <1000 行,最後等於 <35K。假定一個在任何給定時間返回 <1000 個活動查詢結果集中的一個活動緩存集,您將發現此活動緩存集在 Web 伺服器上佔用的記憶體少於 35MB - 這還可以接受)。爲了分頁顯示結果,該進程只遍曆 Web 伺服器的記憶體中存儲的陣列,並對 SQL Server 發出 SELECT 以便只顯示需要顯示的行和列。這又回到了全文查詢僅返回主鍵和排位的概念中 - SELECT(甚至許多這樣的查詢語句)比全文查詢的速度快許多倍。使用 SELECT 而不是與基表合併多個行,並結合多個其他策略,您可以保留 SQL Server 電腦上更多的 CPU 周期,並且更有效、更划算地利用 Web 領域。另一種可以替代 Web 伺服器端緩存的方法是在 SQL Server 自身中緩存結果集,並定義多種用於瀏覽這些結果的方法。雖然本文著重說明 Web 伺服器 (ASP) 級別的應用程式設計,但 SQL Server 的可編程功能還爲生成高性能的 Web 搜索應用程式提供了強大的框架。

小結Microsoft SQL Server 2000 的全文搜索功能爲索引和查詢資料庫中存儲的非結構化文本資料提供了可靠、快速而靈活的方法。如果要廣泛地將這種快速、準確的搜索功能應用于各種應用程式,那麽很有必要充分利用其速度和精確性,來實現全文搜索解決方案。通過分佈計算負載並通過某些巧妙的方式對資料進行組織,可以省下錢來購買其他硬體和軟體,以擺脫因不必要的緩慢查詢帶來的困擾。在開發優秀的搜索應用程式時,通常要考慮到許多因素和注意事項,希望本文提供的資訊和示例對您學習使用 SQL Server 2000 生成出色的 Web 搜索應用程式會有所幫助。附錄 A:實現全文搜索功能的最佳選擇改進全文查詢性能和有效性的一種可行方法是實現“最佳選擇”系統。此系統是一種很簡單的方法,可確保某些與特定查詢運算式匹配的行先於其他行返回。最佳選擇沒有複雜的預編程邏輯(例如,SharePoint Portal Server 就包含這樣的邏輯),因此,通常是首選辦法。在本示例中挑選出最佳選擇,並將唯一的主鍵和一些關鍵字存儲在單獨的表中。FREETEXTTABLE 查詢對(非常小的)最佳選擇表執行,並且從該查詢中返回的任何結果都與對基表的 FREETEXTTABLE 查詢結果一同返回。在給定這些搜索條件下,最先返回的將是所有“最佳選擇”行,隨後是被 MSSearch 視爲關聯程度最高的行(以遞減順序返回)。下面是一個非常簡單的用於創建最佳選擇系統的示例腳本。

use myDb

create table documentTable(ftkey int not null, document ntext)create unique index DTftkey_idx on documentTable(ftKey)

/* 在此插入文檔 (要生成全文索引的所有文檔)*/

-- 爲所有文檔表創建全文目錄和索引exec sp_fulltext_catalog 'documents_cat', 'create', 'f:\ftCats'exec sp_fulltext_table 'documentTable', 'create', 'documents_cat', 'DTftkey_idx'exec sp_fulltext_column 'documentTable', 'document', 'add'exec sp_fulltext_table 'documentTable', 'start_change_tracking'exec sp_fulltext_table 'documentTable', 'start_background_updateindex'

/* 現在創建最佳選擇表和索引 (添加應該始終最先返回的文檔)*/create table bestBets(ftKey int not null, keywords ntext)create unique index BBftkey_idx on bestBets(ftKey)

/* 在此插入最佳選擇*/

-- 爲最佳選擇表創建全文目錄和索引exec sp_fulltext_catalog 'bestBets_cat', 'create', 'f:\ftCats'exec sp_fulltext_table 'bestBets', 'create', 'bestBets_cat', 'BBftkey_idx'exec sp_fulltext_column 'bestBets', 'keywords', 'add'exec sp_fulltext_table 'bestBets', 'start_change_tracking'exec sp_fulltext_table 'bestBets', 'start_background_updateindex'

首先創建了一個通用的“所有文檔”表,用於存儲所有要全文索引的文檔。通常情況下,文檔表中包含其他列,但在本文中,只包含兩列 - 主鍵索引和文檔本身。全文目錄和索引是爲文檔表而創建的。接著創建了“最佳選擇”表,用於存儲所有全文查詢中首先返回的特殊文檔。此表只需具有全文主鍵列和文檔本身(對將某些文檔作爲查詢目標的策略進行優化,包括在該文檔本身不包含的文檔中添加其他關鍵字)。全文目錄和索引是爲最佳選擇表而創建的。最佳選擇表和文檔表可以共用文件(最佳選擇文檔還存儲在常規文檔表中,它們共用同一個主鍵值),也可以相互排斥(最佳選擇文檔只存儲在最佳選擇表中)。爲便於檢索,使最佳選擇表與文檔表互斥更爲容易 - 這樣做就無需從最佳選擇和返回的普通搜索結果行集合中刪除共用操作。另一方面,使用此方法維護文檔可能很難實現,因爲在此方法中,要在查詢中添加邏輯來刪除返回的行集合之間的共用文件。如果給定上面的表,則可以創建兩個存儲過程,以便對最佳選擇表和文檔表進行搜索。可使用 Web 伺服器級別的邏輯或其他存儲過程來緩存和顯示所需結果(與最佳選擇一起使用時,請參閱下面有關緩存、顯示和分頁的一個完整、有效的示例)。首先,創建一個用於檢索最佳選擇行(如果有)的存儲過程:

create procedure BBSearch @searchTerm varchar(1024) as

select [key], [rank] from freetexttable(bestBets, keywords, @searchTerm) order by [rank] desc


確保已對傳入搜索字串進行清理,以避免在伺服器上隨意執行 T-SQL,並確保用單引號將該字串括起。這種情況下,使用 FREETEXTTABLE 比使用 CONTAINSTABLE 要好,因爲 FREETEXTTABLE 將採用尋根溯源功能,並找到與任何搜索詞相匹配的最佳選擇。接下來,第二個存儲過程檢索與常規搜索標準匹配的文檔(如果有):create procedure FTSearch @searchTerm varchar(1024) as


select [key], [rank] from freetexttable(documentTable, keywords, @searchTerm) order by [rank] desc


此外,請確保已清理傳入搜索字串,並用單引號將該字串括起。執行這些存儲過程時,應該在兩個存儲過程中傳入相同的搜索詞,首先執行最佳選擇搜索,然後執行普通全文搜索。下一節更全面地介紹了在構建 Web 搜索應用程式時,如何與其他全文搜索技術一起使用最佳選擇。附錄 B:使用最佳選擇、結果分頁和有效全文查詢邏輯的示例應用程式在本例中,我們實現了一個幾乎利用了本文介紹的所有優化方案的 Web 搜索應用程式。我們對聯機零售商目錄使用簡單的搜索引擎方案,並假定在通信量很高的情況下,所有用戶都期待在很短的回應時間內獲得結果。本示例使用了前一節中的最佳選擇表和存儲過程。此應用程式只是一些可用于實現最佳全文搜索性能的高級策略的簡單示例。本示例使用了 ASP,也可使用 ISAPI、ASP.NET 或其他平臺來實現具有各自優缺點的類似解決方案。會話物件並不一定對所有應用程式都適用,如果使用不當,可能帶來一定程度的危險。在本例中,我們使用會話物件來實現快速有效的緩存機制 - 當然還有許多其他方法可以在不同程度上實現該功能。下面是 ASP 頁的通用代碼:

<% @Language = "VBScript" %><% Response.buffer = true %><html> <head> <title>FT 測試</title></head>

<body><pre>----------------- 開始測試 ------------------

<%

Dim firstRow ' 分頁顯示行時的第一行Dim lastRow ' 分頁顯示行時的最後一行Dim pageSize ' 頁面大小(每次的行數)Dim cn ' 連接物件Dim rs ' FT 主鍵/排位返回的結果集(重復使用)Dim useCache ' 使用緩存或命中 FT(0:不使用;1:使用)Dim alldata ' 要緩存的結果行集合Dim bbdata ' 要緩存的最佳選擇行集合Dim connectionString ' SQL 連接字串

' 確定是否要從緩存獲取資料' 默認爲否,否則接受傳入的資料if (request.Form("useCache") <> "") then useCache = request.Form("useCache")elseif (request.QueryString("useCache") <> "") then useCache = request.QueryString("useCache")else useCache = 0end if

' 設置常量pageSize = 24firstRow = 0lastRow = 23connectionString = <在此輸入您的連接字串>

'----------------------------------------------------------------'' 顯示與最佳選擇/搜索詞匹配的簡單主鍵/排位 ''----------------------------------------------------------------'Private Sub SearchNPage()

Dim p ' 迴圈通過行時的計數器 Dim numRows ' 緩衝/結果集中的總行數

if (useCache <> "1") then ' 獲取最佳選擇/結果並將其緩存

Dim queryArg ' 傳入的查詢詞 if (request.Form("searchTerm") <> "") then queryArg = request.Form("searchTerm") elseif (request.QueryString("searchTerm") <> "") then queryArg = request.QueryString("searchTerm") else response.Write("未提供搜索詞" & VbCrLF) exit sub end if

' 理想情況下,應該在此清理查詢詞... ' 添加自定義的清理邏輯,以防止 ' 隨意執行 SQL

' 調用 CleanString(queryArg)

' 建立與 SQL 的連接 Set cn = Server.CreateObject("ADODB.Connection") cn.Open connectionString

' 從傳入的乾淨字串中獲取最佳選擇匹配項 set rs = cn.Execute("exec BBSearch '" & queryArg & "'")

' 如果有最佳選擇,則獲取最佳選擇 if not(rs.EOF) then bbData = rs.GetRows end if

' 現在從傳入的乾淨字串中獲取普通匹配項 set rs = cn.Execute("exec FTSearch '" & queryArg & "'")

' 如果未返回任何結果,則結束 if (rs.EOF and IsEmpty(bbdata)) then response.Write("沒有匹配的行" & VbCrLF) call ConnClose exit sub end if

' 否則,獲取行 if not(rs.EOF) then alldata = rs.GetRows Session("results") = alldata end if

call ConnClose

else ' 從緩存載入 (usecache=1)

alldata = Session("results")

' 在此獲取要使用的行範圍 if (request.Form("firstRow") <> "") then firstRow = request.Form("firstRow") lastRow = firstRow+pageSize elseif (request.QueryString("firstRow") <> "") then firstRow = request.QueryString("firstRow") lastRow = firstRow+pageSize end if

end if ' useCache<>TRUE

' 對於本應用程式,只是列印出所有最佳選擇 ' (可能比頁面大小大),然後分頁顯示普通結果 ' 此處假設:在使用緩存時,如果沒有新的最佳選擇,' 則使用以前顯示的最佳選擇 if not(IsEmpty(bbdata)) then response.Write("最佳選擇:" & VbCrLf) for p = 0 to ubound(bbdata, 2)response.Write(bbData(0,p) & " " & bbData(1,p) & VbCrLf) next response.Write(VbCrLf) end if

' 返回搜索結果(可能只有最佳選擇) if not(IsEmpty(alldata)) then if uBound(alldata, 2) < lastRow then lastRow = uBound(allData, 2) end if

response.Write("搜索結果:" & VbCrLf)

for p = firstRow to lastRowresponse.Write(allData(0,p) & " " & allData(1,p) & VbCrLf) next end if ' not(IsEmpty(alldata))

End Sub

'----------------------------------------------------------------'' 關閉並清除連接物件 ''----------------------------------------------------------------'Private Sub ConnClose rs.Close Set rs = Nothing cn.Close Set cn = NothingEnd Sub

call SearchNPage

%>

---------------- 測試結束 ----------------

<form action="<本頁>" method="post"><input type=submit value="next <%=pageSize%> rows" NAME="Submit1"><input type=hidden name="useCache" value="1"><input type=hidden name="firstRow" value=<%=lastrow+1%>></form>

</pre> </body></html>


一個簡單的 HTML 表單頁面即可像下面一樣利用上面的腳本:

<html><head><title>輸入搜索詞</title></head>

<body>

<form action="<搜索 ASP 頁面>" method="post">搜索詞:<input name="searchTerm"><p><input type="submit" value="Search"></form>

</body></html>


正如以上兩個代碼示例所示,創建可執行有效全文查詢(用最佳選擇完成)並緩存和分頁顯示結果的 Web 應用程式,並不需要花費太多的工夫。只需使用最低的系統開銷,即可添加用於提供其他資料、增強最佳選擇的外觀以及在搜索結果中導航的邏輯(此外,強烈建議您實現其他用於錯誤處理、安全設置和清理傳入資料的嚴密邏輯)。通過上面的高級建議和示例,使用 SQL Server 2000 全文搜索設計和實現快速可縮放的 Web 搜索應用程式就是輕而易舉的事情了。


附錄 C:資源Full-Text Search Deployment(英文)http://support.microsoft.com/default.aspx?scid=/support/sql/content/2000papers/fts_white%20paper.asp 是那些初次接觸全文搜索的用戶的最佳參考。介紹了填充方法及硬體和軟體需求,並爲使用 SQL Server 2000 全文搜索提供了提示、技巧和其他文檔。全文搜索公共新聞組 (microsoft.public.sqlserver.fulltext)查找有關全文搜索問題的答案以及有用提示和技巧的理想場所。全文搜索新聞組是 SQL Server 開發小組和博學的 Microsoft MVP 成員經常光顧的場所。

根據一張表的內容去更新另外一張表的內容

有兩個表
1, out_proudctlist(出庫物品清單)
id outlist_id product_id out_num
1 out1 11 2
2 out1 12 5
3 out2 11 2
.......


2, product(物品資訊)
id product_id product_name stock_num
1 11 牛奶 20
2 12 涼茶 20

update t
set stock_num=t.stock_num-A.out_num
from product t
join (
select product_id
,sum(out_num) as 'out_num'
from out_proudctlist
group by product_id
)A on t.product_id=A.product_id

雙擊圖片,彈出儲存圖片的對話方塊

<img src="1.jpg">
<SCRIPT LANGUAGE="JavaScript">
document.ondblclick = function()
{
var e = window.event.srcElement;
if(e.tagName=="IMG")
{
var win=window.open(e.src, "_blank", "top=1200px,left=1200px");
win.document.execCommand('SaveAs');
win.opener=null;
win.close();
}
}
</SCRIPT>

MS SQL Server 如何實現自動備份

把這段代碼配置到作業排程中,然後配置好作業,定時執行!
作業排程教學 http://e.1asphost.com/windymoon/blog/blogview.asp?logID=24

declare @strsql varchar(1000), --執行語句
@strdirname varchar(50),--建立文件夾名
@strcmd varchar(50), --執行命令名
@strdate varchar(50)
set @strsql='backup database SZ to disk=''d:\backup\SZ\'
set @strdirname=replace(substring(convert(varchar(20),getdate(),120),1,10),'-','')
set @strcmd='md d:\backup\SZ\'
set @strcmd=@strcmd+@strdirname
--取得當天日期,格式爲yyyy-mm-dd
set @strdate=substring(convert(varchar(50),getdate(),120),1,10)
exec master..xp_cmdshell @strcmd
set @strsql=@strsql+@strdirname+'\SZ.dat''with init,nounload,noskip,noformat'
print @strsql
exec (@strsql)

使用TSQL建立作業排程

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_createjob]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_createjob]
GO

create proc p_createjob
@jobname varchar(100), --作業排程名稱
@sql varchar(8000), --要執行的命令
@serverName sysname='', --job server名
@dbname sysname='', --默認爲當前的資料庫名
@freqtype varchar(6)='day', --時間周期,month 月,week 周,day 日
@fsinterval int=1, --相對於每日的重復次數
@time int=170000 --開始執行時間,對於重復執行的作業排程,將從0點到23:59分
as
if isnull(@dbname,'')='' set @dbname=db_name()

--建立作業排程
exec msdb..sp_add_job @job_name=@jobname

--建立作業排程步驟
exec msdb..sp_add_jobstep @job_name=@jobname,
@step_name = '資料處理',
@subsystem = 'TSQL',
@database_name=@dbname,
@command = @sql,
@retry_attempts = 5, --重試次數
@retry_interval = 5 --重試間隔

--建立調度
declare @ftype int,@fstype int,@ffactor int
select @ftype=case @freqtype when 'day' then 4
when 'week' then 8
when 'month' then 16 end
,@fstype=case @fsinterval when 1 then 0 else 8 end
if @fsinterval<>1 set @time=0
set @ffactor=case @freqtype when 'day' then 0 else 1 end

EXEC msdb..sp_add_jobschedule @job_name=@jobname,
@name = '時間安排',
@freq_type=@ftype , --每天,8 每周,16 每月
@freq_interval=1, --重復執行次數
@freq_subday_type=@fstype, --是否重復執行
@freq_subday_interval=@fsinterval, --重復周期
@freq_recurrence_factor=@ffactor,
@active_start_time=@time --下午17:00:00分執行

if @servername=''
set @servername=@@servername
EXEC msdb..sp_add_jobserver @job_name = @jobname,
@server_name = @servername

go

--調用
--每月執行的作業排程
exec p_createjob @jobname='mm'
,@sql='insert A select ''AAA'''
,@servername='FUDAN-OXI9Y1PYT'
,@dbname='test'
,@freqtype='month'
,@time='000000'

將sql server裏的資料導出到文本

想把一張Table裏的資料導出到文本中,但是需要將每條記錄導成一個文本,而不是全部導成一個文本,
比如現有表如下
id(varchar(50) pk) detail(text)
aaa 11111
bbb 43424
ccc 324234

導出後指定目錄裏面應該有三個文件:aaa.txt, bbb.txt, ccc.txt, 文本內容爲相應的detail列中的內容,也就是說,將ID欄位作爲檔案名,detail欄位元作爲文本內容,如何以存儲過程實現 ?

--處理示例

--測試表
create table tb(id varchar(50) primary key,detail text)
insert tb select 'aaa','11111'
union all select 'bbb','43424'
union all select 'ccc','324234'
go


--處理的存儲過程
create proc p_export
@path nvarchar(1000) --導出的文字檔案保存的目錄
as
declare @s nvarchar(4000)
if isnull(@path,'')='' set @path='c:\'
else if right(@path,1)<>'\' set @path=@path+'\'


--用游標建構每條記錄的bcp導出語句,BCP的語法參考sql help
declare tb cursor local
for
select 'BCP "select detail from '
+quotename(db_name())
+'..tb where id='
+quotename(id,N'''')
+'" queryout "'+@path
+id+'.txt" /T /w'
from tb
open tb
fetch tb into @s
while @@fetch_status=0
begin

--調用xp_cmdshell存儲過程執行bcp進行導出處理
exec master..xp_cmdshell @s,no_output
--爲方便觀察bcp語句,將處理的語句列印出來
print(@s)
fetch tb into @s
end
close tb
deallocate tb
go


--調用
exec p_export 'c:\'
go


--刪除測試
drop table tb
drop proc p_export

一些 SQL 的 Extended Stroe Procedure

在sql server中擴展存儲過程直接使用的機會不是很多
我把我知道的幾個有用的擴展存儲過程使用方式總結如下:

--獲得MS SQL的版本號
execute master..sp_msgetversion
go

--得到硬碟文件資訊
--參數說明:目錄名,目錄深度,是否顯示文件
execute master..xp_dirtree 'c:'
go
execute master..xp_dirtree 'c:',1
go
execute master..xp_dirtree 'c:',1,1
go

--列出伺服器上安裝的所有OLEDB提供的程式
execute master..xp_enum_oledb_providers
go

--列出伺服器上安裝的所有內碼表
execute master..xp_enumcodepages
go

--列出伺服器上配置的dsn
execute master..xp_enumdsn
go

--列出sql server錯誤日誌列表,最後更新時間
execute master..xp_enumerrorlogs
go

--列出伺服器上所有windows本地組
execute master..xp_enumgroups
go

--檢測文件存在性
execute master..xp_fileexist 'c:\a.bak'
go

declare @flag int
exec master..xp_fileexist 'c:\abc.bak',@flag out
if @flag=1
begin
print 'exist'
end
else
begin
print 'no exist'
end
go

--列出伺服器上固定驅動器,以及每個驅動器的可用空間
execute master..xp_fixeddrives
go

--得到當前sql server伺服器的電腦名稱
execute master..xp_getnetname
go

--列出當前錯誤日誌的具體內容
EXEC [master].[dbo].[xp_readerrorlog]
go

--列出指定目錄的所有下一級子目錄
EXEC [master].[dbo].[xp_subdirs] 'c:\WINNT'
go

---列出驅動器的名稱
--以位元組爲單位的空閒空間(low free)
--以驅動器類型:軟盤機(1),硬碟(2),cd-rom(8)
EXEC [master].[dbo].[xp_availablemedia]
go

--效果如下:
name low free high free media type
C:\ 1270386688 0 2
D:\ 1726824448 2 2
E:\ 875053056 10 2
F:\ 0 0 8

(所影響的行數爲 4 行)

還有在[master].[dbo].[sp_addlogin]裏面有加密函數pwdencrypt,大家感興趣可以試試

希望上面提到的知識對你有所提示
當然歡迎交流和指正

author:aierong
blog:http://www.cnblogs.com/aierong
email:aierong@126.com

當SQL Server資料庫崩潰時如何恢復

任何資料庫系統都無法避免崩潰的狀況,即使你使用了Clustered,雙機熱備……仍然無法完全根除系統中的單點故障,何況對於大部分用戶來說,無法承受這樣昂貴的硬體投資。所以,在系統崩潰的時候,如何恢復原有的寶貴資料就成爲一個極其重要的問題了。在恢復的時候,最理想的情況就是你的資料檔案和日誌文件都完好無損了,這樣只需要sp_attach_db,把資料檔案附加到新的資料庫上即可,或者在停機的時候把所有資料檔案(一定要有master等)都copy到原有路徑下也行,不過一般不推薦這樣的做法,sp_attach_db比較好,雖然麻煩許多。但是呢,一般資料庫崩潰的時候系統是未必能有時間把未完成的事務和髒頁等寫入磁片的,這樣的情況sp_attach_db就會失敗。那麽,寄期望於DBA制定了一個良好的災難恢復計劃吧。按照你的恢復計劃,還原最新的完全備份,增量備份或者事務日誌備份,然後如果你的活動事務日誌還能讀得出來的話,恭喜你!你可以還原到崩潰前的狀態。
一般的單位都是沒有專職的DBA的,如果沒有可用的備份,更可能是最近一次備份的時間過於久遠而導致不可接受的資料損失,而且你的活動事務日誌也處於不可用的狀態,那就是最麻煩的情況了。不幸的很的是,一般資料庫崩潰都是由於存儲子系統引起的,而這樣的情況是幾乎不可能有可用的日誌用於恢復的。那麽就只好試一下這些方案了。當然,是要求至少你的資料檔案是存在的,要是資料檔案、日誌文件和備份都沒有了的話,別找我,你可以到樓頂上去唱“神啊,救救我吧”。
首先,你可以試一下sp_attach_single_file_db,試著恢復一下你的資料檔案,雖然能恢復的可能性不大,不過假如這個資料庫剛好執行了一個checkpoint的話,還是有可能成功的。如果你沒有好到有摸彩票的手氣,最重要的資料庫沒有像你期盼的那樣attach上去,不要氣餒,還是有別的方案的。我們可以試著重新建立一個log,先把資料庫設置爲emergency mode,sysdatabases的status爲32768 就表示資料庫處於此狀態。不過系統表是不能隨便改的,設置一下先
Use MasterGosp_configure 'allow updates', 1reconfigure with overrideGo
然後
update sysdatabases set status = 32768 where name = ''
現在,祈求滿天神佛的保佑吧,重新建立一個log文件。成功的機會還是相當大的,系統一般都會認可你新建立的日誌。如果沒有報告什麽錯誤,現在就可以松一口氣了。雖然資料是恢復了,可是別以爲事情就算完成了,正在進行的事務肯定是丟失了,原來的資料也可能受到一些損壞。先把SQL Server 重新啓動一下,然後檢查你的資料庫吧。先設置成單用戶模式,然後做
dbccsp_dboption '', 'single user', 'true'DBCC CHECKDB('')
如果沒有什麽大問題就可以把資料庫狀態改回去了,記得別忘了把系統表的修改選項關掉。
update sysdatabases set status = 28 where name = '' --
當然你的資料庫狀態可能不是這個,自己改爲合適的值吧。也可以用
sp_resetstatusgosp_configure 'allow updates', 0reconfigure with overrideGocheckdb
的時候可能報告有一些錯誤,這些錯誤的資料你可能就只好丟棄了。checkdb有幾種修復選項,自己看著用吧,不過最後你可能還是得用REPAIR_ALLOW_DATA_LOSS,完成所有修復。chekcdb並不能完成所有的修復,我們需要更進一步的修復,用DBCC CHECKTABLE對每一個表做檢查吧。表的列表可以用sysobjects裏面得到,把OBJECTPROPERTY是IsTable的全部找出來檢查一下吧,這樣能夠基本上解決問題了,如果還報告錯誤,試著把資料select into到另一張表檢查一下。這些都做完了之後,把所有索引、視圖、存儲過程、觸發器等重新建立一下。DBCC DBREINDEX也許可以幫你一些忙。

精典SQL FAQ收藏

精典SQL FAQ收藏

1. 行列轉換--普通
假設有張學生成績表(CJ)如下
Name Subject Result
張三 語文 80
張三 數學 90
張三 物理 85
李四 語文 85
李四 數學 92
李四 物理 82
想變成
姓名 語文 數學 物理
張三 80 90 85
李四 85 92 82

declare @sql varchar(4000)
set @sql = 'select Name'
select @sql = @sql + ',sum(case Subject when '''+Subject+''' then Result end) ['+Subject+']' from (select distinct Subject from CJ) as aselect @sql = @sql+' from test group by name'exec(@sql)


2. 行列轉換--合併
有表A, id pid 1 1 1 2 1 3 2 1 2 2 3 1
如何化成表B: id pid 1 1,2,3 2 1,2 3 1
創建一個合併的函數
create function fmerg(@id int)returns varchar(8000)
as
begin
declare @str varchar(8000)
set @str=''select @str=@str+','+cast(pid as varchar) from 表A
where id=@idset @str=right(@str,len(@str)-1)return(@str)
End
go

--調用自定義函數得到結果select distinct id,dbo.fmerg(id) from 表A

3. 如何取得一個資料表的所有列名
方法如下:先從SYSTEMOBJECT系統表中取得資料表的SYSTEMID,然後再SYSCOLUMN表中取得該資料表的所有列名。SQL語句如下:
declare @objid int,@objname char(40)
set @objname = 'tablename'select @objid = id from sysobjects where id = object_id(@objname)
select 'Column_name' = name from syscolumns where id = @objid order by colid


是不是太簡單了? 呵呵 不過經常用阿.

4. 通過SQL語句來更改用戶的密碼
修改別人的,需要sysadmin role EXEC sp_password NULL, 'newpassword', 'User'
如果帳號爲SA執行EXEC sp_password NULL, 'newpassword', sa

5. 怎麽判斷出一個表的哪些欄位不允許爲空?
select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where IS_NULLABLE='NO' and TABLE_NAME=tablename

6. 如何在資料庫裏找到含有相同欄位的表?
a. 查已知列名的情況
SELECT b.name as TableName,a.name as columnname From syscolumns a INNER JOIN sysobjects b ON a.id=b.id AND b.type='U' AND a.name='你的欄位名字'
b. 未知列名查所有在不同表出現過的列名
Select o.name As tablename,s1.name As columnname From syscolumns s1, sysobjects o Where s1.id = o.id And o.type = 'U' And Exists ( Select 1 From syscolumns s2 Where s1.name = s2.name And s1.id <> s2.id )

7. 查詢第xxx行資料
假設id是主鍵: select * from (select top xxx * from yourtable) aa where not exists(select 1 from (select top xxx-1 * from yourtable) bb where aa.id=bb.id) 如果使用游標也是可以的 fetch absolute [number] from [cursor_name] 行數爲絕對行數

8. SQL Server日期計算
a. 一個月的第一天SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)
b. 本周的星期一SELECT DATEADD(wk, DATEDIFF(wk,0,getdate()), 0)
c. 一年的第一天SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)
d. 季度的第一天SELECT DATEADD(qq, DATEDIFF(qq,0,getdate()), 0)
e. 上個月的最後一天 SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(mm,0,getdate()), 0))
f. 去年的最後一天SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))
g. 本月的最後一天SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate())+1, 0))
h. 本月的第一個星期一select DATEADD(wk, DATEDIFF(wk,0, dateadd(dd,6-datepart(day,getdate()),getdate())), 0)
i. 本年的最後一天SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate())+1, 0))。

避免asp的SQL的執行效率低

今天在網路上看到這一篇文章, 很實用, 把它貼出來, 由於轉載的網站亦不知其原作者僅說為網路文章, 因為無法列出原作者, 若此文為您所創, 歡迎與我聯繫, 我會將您的大名給列上去的, 謝謝!

方法一、儘量使用複雜的SQL來代替簡單的一堆 SQL.
同樣的事務,一個複雜的SQL完成的效率高於一堆簡單SQL完成的效率。有多個查詢時,要善於使用JOIN。
oRs=oConn.Execute("SELECT * FROM Books")
while not oRs.Eof
strSQL = "SELECT * FROM Authors WHERE AuthorID="&oRs("AuthorID") oRs2=oConn.Execute(strSQL)
Response.write oRs("Title")&">>"&oRs2("Name")&"
&q uot;
oRs.MoveNext()
wend

要比下面的代碼慢:
strSQL="SELECT Books.Title,Authors.Name FROM Books JOIN Authors ON Authors.AuthorID=Books.AuthorID"
oRs=oConn.Execute(strSQL)
while not oRs.Eof
Response.write oRs("Title")&">>"&oRs("Name")&"
&qu ot;
oRs.MoveNext()
wend


方法二、儘量避免使用可更新 Recordset
oRs=oConn.Execute("SELECT * FROM Authors WHERE AuthorID=17",3,3)
oRs("Name")="DarkMan"
oRs.Update()

要比下面的代碼慢:
strSQL = "UPDATE Authors SET Name='DarkMan' WHERE AuthorID=17"
oConn.Execute strSQL


方法三、更新資料庫時,儘量採用批處 理更新
將所有的SQL組成一個大的批次處理SQL,並一次運行;這比一個一個地更新資料要有效率得多。這樣也更加滿足你進行事務處理 的需要:
strSQL=""
strSQL=strSQL&"SET XACT_ABORT ON;" & vbcrlf
strSQL=strSQL&"BEGIN TRANSACTION;" & vbcrlf
strSQL=strSQL&"INSERT INTO Orders(OrdID,CustID,OrdDat) VALUES('9999','1234',GETDATE());" & vbcrlf
strSQL=strSQL&"INSERT INTO OrderRows(OrdID,OrdRow,Item,Qty) VALUES('9999','01','G4385',5);" & vbcrlf
strSQL=strSQL&"INSERT INTO OrderRows(OrdID,OrdRow,Item,Qty) VALUES('9999','02','G4726',1);" & vbcrlf
strSQL=strSQL&"COMMIT TRANSACTION;" & vbcrlf
strSQL=strSQL&"SET XACT_ABORT OFF;" & vbcrlf
oConn.Execute(strSQL)

其中,SET XACT_ABORT OFF 語句告訴SQL Server,如果下面的事務處理過程中,如果遇到錯誤,就取消已經完成的事務。

方法四、資料庫索引
那些將在Where子句中出現的欄位,你應該首先考慮建立索引;那些需要排序的欄位,也應該在考慮之列 。
在MS Access中建立索引的方法:在Access裏面選擇需要索引的表,點擊“設計”,然後設置相應欄位的索引.
在MS SQL Server中建立索引的方法:在SQL Server管理器中,選擇相應的表,然後“設計表”,點擊右鍵,選擇“Properties”,選擇“indexes/keys”

方法五、避免使Text欄位太大
當字串的值大小不固定時,用varchar比用char的效果要好 些。我曾經看到一個例副程式,欄位被定義爲TEXT(255),但是他的取值經常只有20個字元。這個資料表有50k個記錄,從而使這個資料庫很大,大的資料庫必然較慢。

插入 unicode value 到 Table

insert into TableName values("N'名字'")

至於資料庫的 schema 也要換為 unicode, 例如
原本 filed type 為 varchar 要變更為 nvarchar
原本 filed type 為 text 要變更為 ntext

ASP 使用 unicode 來 coding 時

要加

<%@CodePage=65001%>
<%
session.codepage=65001
Response.Charset="utf-8"
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
......
</body>
</html>


2007年2月9日 星期五

ASP 的 Query String 以 unicode 傳送的方法

原本寫法是
<a href="a.asp?p=同事>

改成
<a href="a.asp?p=<%=escape("同事")%>>

要轉回原本的字
<%=unescape("%u1234%u4568")%>

表格顏色在滑鼠經過時改變顏色


<td onMouseOver="style.backgroundColor='#cccccc'" onMouseOut="style.backgroundColor='#ffffff'">

2007年2月8日 星期四

半透明的層

1) 要先定義一個 CSS 的樣式
<style type="text/css">
.halfalpha {
background-color:#000000;
filter: Alpha(Opacity:50);
}
</style>


2) 應用在層的標籤裡
<div class="halfalpha">

URL Encode 與 Decode 的 Function

Public Function urlDecode(s As String) As String
If Len(s) = 0 Then Exit Function
Dim i As Integer
Dim tmp As String
Dim c As String
For i = 1 To Len(s)
c = Mid$(s, i, 1)
If c = "+" Then c = " "
If c = "%" Then
c = Chr$("&H" + Mid$(s, i + 1, 2))
i = i + 2
End If
tmp = tmp + c
Next i
urlDecode = tmp
End Function

Public Function urlEncode(s As String) As String
If Len(s) = 0 Then Exit Function

Dim tmp As String
Dim c As String
Dim i As Integer

For i = 1 To Len(s)
c = Mid(s, i, 1)
If (Asc(c) >= 65 And Asc(c) <= 90) _
Or (Asc(c) >= 97 And Asc(c) <= 122) _
Or (Asc(c) >= 48 And Asc(c) <= 58) _
Or Asc(c) = 38 _
Or (Asc(c) >= 45 And Asc(c) <= 47) _
Or Asc(c) = 58 Or Asc(c) = 61 _
Or Asc(c) = 63 Or Asc(c) = 126 Then
tmp = tmp + c
Else
tmp = tmp + "%" + Hex(Asc(c))
End If
Next i
urlEncode = tmp
End Function

檔名以 Timestamp 來命名的coding

Public Sub setFilename(filename__param)
myDate = DatePart("yyyy", Now()) & "_" & DatePart("m", Now()) & "_" & DatePart("d", Now())
myTime = Hour(Now()) & "_" & Minute(Now()) & "_" & Second(Now())
filename = myDate & "__" & myTime & ".csv"
End Sub

使用 radio 時, 想讓滑鼠點到 input box 時自動去切換


<form action="smssent.asp" method="post" name="smssentform" OnSubmit="return checkinput(this,'add');">
<input type="radio" name="whensent" value="asap" checked><label class="normalFont">馬上傳送</label></nobr>
<input type="radio" name="whensent" value="setdate"><label class="normalFont">
西元<input type="text" name="wyear" maxlength="4" class="recTextbox" value="<%=year(now)%>" onclick="smssentform.whensent[1].click();">年<input type="text" name="wmonth" maxlength="2" class="recTextbox" value="<%=month(now)%>" onclick="smssentform.whensent[1].click();">月<input type="text" name="wday" maxlength="2" class="recTextbox" value="<%=day(now)%>" onclick="smssentform.whensent[1].click();">日</label></nobr>

有關 javascript 的 Month

今天在寫計算日期時發現, javascript 在月份的計算上跟平常我們習慣用的方法不同, 像getMonth()時, 實際上取得的月份會是少了一個月, 這是因為javascript的月份是從0開始起算, 所以是0-11
因此在使用 setMonth() 時, 想 set 至 9 月份時必須要 setMonth(9-1), 否則會取到10月的

這是我歷經多次試驗才抓出來的問題 =.=|||
粉吐血吧, 居然javascript的月份是從 0 起算的

跨 Table 要 group 又要 sum 粉麻煩ㄋ

搞好久 sr_body 一直group不起來, 結果原來是因為它是text的欄位 =.=|||
所以要用 substring() Function 來取, 最大值到 4000 個字元

SELECT sr_sd_id, sr_dlvtime, SUM(sr_pointUsed) AS sr_pointUsed, substring(sr_body, 1, 4000) as sr_body FROM smsReceiver
WHERE sr_sd_id in ( select sd_id from smsDir where sd_Status='0')
group by sr_sd_id, sr_dlvtime, substring(sr_body, 1, 4000)

SQL 在select時直接抓取特定日期的期間方法

select wll_clientip, wll_stamp, wll_fail from WebLoginLog
where wll_stamp between dateadd(month, -3, getdate()) and getdate()

dateadd()為SQL提供的Function, 第一個參數可以是year, month, day, hour, minute, second 甚至到millisecond
第2個參數, 負數為之前時間差, 正數為之後的時間差

javascript的replace()跟一般的用法不一樣喔

一般而言, 用 replace() 就可以取代所有的字, 但是 javascript 要用參數才能, 否則只會取代第一個找到的字......或許這也是比較好的方式吧 =.=
因為有些情況的確是只想要取代一個而已.......
原本照一般的用法是 string.replace('要尋找的字', '被取代的字');
要想全部取代的話, 用法要變成
string.replace(/\要尋找的字/g, '被取代的字');
呵呵, 又多學了一招了~~ ^@^