[XHTML无图版]
bbs.taihainet.com民坊社区[网络学院]SQL相关
主题:SQL相关

SQL核心语句

插入数据

向表中添加一个新记录,你要使用SQL INSERT 语句。这里有一个如何使用这种语句的例子:

INSERT mytable (mycolumn) VALUES (‘some data’)

这个语句把字符串’some data’插入表mytable的mycolumn字段中。将要被插入数据的字段的名字在第一个括号中指定,实际的数据在第二个括号中给出。

INSERT 语句的完整句法如下:

INSERT [INTO] {table_name|view_name} [(column_list)] {DEFAULT VALUES |

Values_list | select_statement}

如果一个表有多个字段,通过把字段名和字段值用逗号隔开,你可以向所有的字段中插入数据。假设表mytable有三个字段first_column,second_column,和third_column。下面的INSERT语句添加了一条三个字段都有值的完整记录:

INSERT mytable (first_column,second_column,third_column)

VALUES (‘some data’,’some more data’,’yet more data’)

注意

你可以使用INSERT语句向文本型字段中插入数据。但是,如果你需要输入很长的字符串,你应该使用WRITETEXT语句。这部分内容对本书来说太高级了,因此不加讨论。要了解更多的信息,请参考Microsoft SQL Sever 的文档。

如果你在INSERT 语句中只指定两个字段和数据会怎么样呢?换句话说,你向一个表中插入一条新记录,但有一个字段没有提供数据。在这种情况下,有下面的四种可能:

如果该字段有一个缺省值,该值会被使用。例如,假设你插入新记录时没有给字段third_column提供数据,而这个字段有一个缺省值’some value’。在这种情况下,当新记录建立时会插入值’some value’。

如果该字段可以接受空值,而且没有缺省值,则会被插入空值。

如果该字段不能接受空值,而且没有缺省值,就会出现错误。你会收到错误信息:

The column in table mytable may not be null.

最后,如果该字段是一个标识字段,那么它会自动产生一个新值。当你向一个有标识字段的表中插入新记录时,只要忽略该字段,标识字段会给自己赋一个新值。

注意

向一个有标识字段的表中插入新记录后,你可以用SQL变量@@identity来访问新记录

的标识字段的值。考虑如下的SQL语句:

INSERT mytable (first_column) VALUES(‘some value’)

INSERT anothertable(another_first,another_second)

VALUES(@@identity,’some value’)

如果表mytable有一个标识字段,该字段的值会被插入表anothertable的another_first字段。这是因为变量@@identity总是保存最后一次插入标识字段的值。

字段another_first应该与字段first_column有相同的数据类型。但是,字段another_first不能是应该标识字段。Another_first字段用来保存字段first_column的值。

删除记录

要从表中删除一个或多个记录,需要使用SQL DELETE语句。你可以给DELETE 语句提供WHERE 子句。WHERE子句用来选择要删除的记录。例如,下面的这个DELETE语句只删除字段first_column的值等于’Delete Me’的记录:

DELETE mytable WHERE first_column=’Deltet Me’

DELETE 语句的完整句法如下:

DELETE [FROM] {table_name|view_name} [WHERE clause]

在SQL SELECT 语句中可以使用的任何条件都可以在DELECT 语句的WHERE子句 中使用。例如,下面的这个DELETE语句只删除那些first_column字段的值为’goodbye’或second_column字段的值为’so long’的记录:

DELETE mytable WHERE first_column=’goodby’ OR second_column=’so long’

如果你不给DELETE 语句提供WHERE 子句,表中的所有记录都将被删除。你不应该有这种想法。如果你想删除应该表中的所有记录,应使用第十章所讲的TRUNCATE TABLE语句。

注意

为什么要用TRUNCATE TABLE 语句代替DELETE语句?当你使用TRUNCATE TABLE语句时,记录的删除是不作记录的。也就是说,这意味着TRUNCATE TABLE 要比DELETE快得多。

更新记录

要修改表中已经存在的一条或多条记录,应使用SQL UPDATE语句。同DELETE语句一样,UPDATE语句可以使用WHERE子句来选择更新特定的记录。请看这个例子:

UPDATE mytable SET first_column=’Updated!’ WHERE second_column=’Update Me!’

这个UPDATE 语句更新所有second_column字段的值为’Update Me!’的记录。对所有被选中的记录,字段first_column的值被置为’Updated!’。

下面是UPDATE语句的完整句法:

UPDATE {table_name|view_name} SET [{table_name|view_name}]

{column_list|variable_list|variable_and_column_list}

[,{column_list2|variable_list2|variable_and_column_list2}…

[,{column_listN|variable_listN|variable_and_column_listN}]]

[WHERE clause]

注意

你可以对文本型字段使用UPDATE语句。但是,如果你需要更新很长的字符串,应使用UPDATETEXT语句。这部分内容对本书来说太高级了,因此不加讨论。要了解更多的信息,请参考Microsoft SQL Sever 的文档。

如果你不提供WHERE子句,表中的所有记录都将被更新。有时这是有用的。例如,如果你想把表titles中的所有书的价格加倍,你可以使用如下的UPDATE 语句:

你也可以同时更新多个字段。例如,下面的UPDATE语句同时更新first_column,second_column,和third_column这三个字段:

UPDATE mytable SET first_column=’Updated!’

Second_column=’Updated!’

Third_column=’Updated!’

WHERE first_column=’Update Me1’

技巧

SQL忽略语句中多余的空格。你可以把SQL语句写成任何你最容易读的格式。

用SELECT 创建记录和表

你也许已经注意到,INSERT 语句与DELETE语句和UPDATE语句有一点不同,它一次只操作一个记录。然而,有一个方法可以使INSERT 语句一次添加多个记录。要作到这一点,你需要把INSERT 语句与SELECT 语句结合起来,象这样:

INSERT mytable (first_column,second_column)

SELECT another_first,another_second

FROM anothertable

WHERE another_first=’Copy Me!’

这个语句从anothertable拷贝记录到mytable.只有表anothertable中字段another_first的值为’Copy Me!’的记录才被拷贝。

当为一个表中的记录建立备份时,这种形式的INSERT 语句是非常有用的。在删除一个表中的记录之前,你可以先用这种方法把它们拷贝到另一个表中。

如果你需要拷贝整个表,你可以使用SELECT INTO 语句。例如,下面的语句创建了一个名为newtable的新表,该表包含表mytable的所有数据:

SELECT * INTO newtable FROM mytable

你也可以指定只有特定的字段被用来创建这个新表。要做到这一点,只需在字段列表中指定你想要拷贝的字段。另外,你可以使用WHERE 子句来限制拷贝到新表中的记录。下面的例子只拷贝字段second_columnd的值等于’Copy Me!’的记录的first_column字段。

SELECT first_column INTO newtable

FROM mytable

WHERE second_column=’Copy Me!’

使用SQL修改已经建立的表是很困难的。例如,如果你向一个表中添加了一个字段,没有容易的办法来去除它。另外,如果你不小心把一个字段的数据类型给错了,你将没有办法改变它。但是,使用本节中讲述的SQL语句,你可以绕过这两个问题。

例如,假设你想从一个表中删除一个字段。使用SELECT INTO 语句,你可以创建该表的一个拷贝,但不包含要删除的字段。这使你既删除了该字段,又保留了不想删除的数据。

如果你想改变一个字段的数据类型,你可以创建一个包含正确数据类型字段的新表。创建好该表后,你就可以结合使用UPDATE语句和SELECT 语句,把原来表中的所有数据拷贝到新表中。通过这种方法,你既可以修改表的结构,又能保存原有的数据。
实例讲解ASP实现抓取网上房产信息
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta http-equiv="refresh" content="300;URL=steal_house.asp">
</head> <body>
<%
on error resume next
'
Server.ScriptTimeout = 999999
'========================================================
'字符编码函数
'====================================================
Function BytesToBstr(body,code)
        dim objstream
        set objstream = Server.CreateObject("adodb.stream")
        objstream.Type = 1
        objstream.Mode =3
        objstream.Open
        objstream.Write body
        objstream.Position = 0
        objstream.Type = 2
        objstream.Charset =code
        BytesToBstr = objstream.ReadText 
        objstream.Close
        set objstream = nothing
End Function
'取行字符串在另一字符串中的出现位置
Function Newstring(wstr,strng)
        Newstring=Instr(lcase(wstr),lcase(strng))
        if Newstring<=0 then Newstring=Len(wstr)
End Function
'替换字符串函数
function ReplaceStr(ori,str1,str2)
ReplaceStr=replace(ori,str1,str2)
end function
'====================================================
function ReadXml(url,code,start,ends)
set oSend=createobject("Microsoft.XMLHTTP")
SourceCode = oSend.open ("GET",url,false)
oSend.send()
ReadXml=BytesToBstr(oSend.responseBody,code )
start=Instr(ReadXml,start)
ReadXml=mid(ReadXml,start)
ends=Instr(ReadXml,ends)
ReadXml=left(ReadXml,ends-1)
end function
function SubStr(body,start,ends)
start=Instr(body,start)
SubStr=mid(body,start+len(start)+1)
ends=Instr(SubStr,ends)
SubStr=left(SubStr,ends-1)
end function
dim getcont,NewsContent
dim url,title
url="http://www.***.com"'新闻网址knowsky.com
getcont=ReadXml(url,"gb2312","<table class=k2 border=""0""","</table>")
getcont=RegexHtml(getcont)
dim KeyId,NewsClass,City,Position,HouseType,Level,Area,Price,Demostra
dim ContactMan,Contact
for i=2 to ubound(getcont)
 response.Write(getcont(i)&"__<br>")
 
 tempLink=mid(getcont(i),instr(getcont(i),"href=""")+6,instr(getcont(i),""" onClick")-10)
 tempLink=replace(tempLink,"../","")
 
 response.Write(i&":"&tempLink&"<br>")
 NewsContent=ReadXml(tempLink,"gb2312","<td valign=""bottom"" width=""400"">","<hr width=""760"" noshade size=""1"" color=""#808080""> ")
 NewsContent=RemoveHtml(NewsContent)
 NewsContent=replace(NewsContent,VbCrLf,"")
 NewsContent=replace(NewsContent,vbNewLine,"")
 NewsContent=replace(NewsContent," ","")
 NewsContent=replace(NewsContent," ","")
 NewsContent=replace(NewsContent,"&nbsp;","")
 NewsContent=replace(NewsContent,"\n","")
 NewsContent=replace(NewsContent,chr(10),"")
 NewsContent=replace(NewsContent,chr(13),"")
 '===============get Content=======================
 response.Write(NewsContent)
 KeyId=SubStr(NewsContent,"列号:","信息类别:")
 NewsClass=SubStr(NewsContent,"类别:","所在城市:")
 City=SubStr(NewsContent,"城市:","房屋具体位置:")
 Position=SubStr(NewsContent,"位置:","房屋类型:")
 HouseType=SubStr(NewsContent,"类型:","楼层:")
 Level=SubStr(NewsContent,"楼层:","使用面积:")
 Area=SubStr(NewsContent,"面积:","房价:")
 Price=SubStr(NewsContent,"房价:","其他说明:")
 Demostra=SubStr(NewsContent,"说明:","联系人:")
 ContactMan=SubStr(NewsContent,"联系人:","联系方式:")
 Contact=SubStr(NewsContent,"联系方式:","信息来源:")
 response.Write("总序列号:"&KeyId&"<br>")
 response.Write("信息类别:"&NewsClass&"<br>")
 response.Write("所在城市:"&City&"<br>")
 response.Write("房屋具体位置:"&Position&"<br>")
 response.Write("房屋类型:"&HouseType&"<br>")
 response.Write("楼层:"&Level&"<br>")
 response.Write("使用面积:"&Area&"<br>")
 response.Write("房价:"&Price&"<br>")
 response.Write("其他说明:"&Demostra&"<br>")
 response.Write("联系人:"&ContactMan&"<br>")
 response.Write("联系方式:"&Contact&"<br>")
 'title=RemoveHTML(aa(i))
 'response.Write("title:"&title)
 for n=0 to application.Contents.count
   if(application.Contents(n)=KeyId) then
    ifexit=true    
   end if  
 next 
 if not ifexit then
   application(time&i)=KeyId
 '添加到数据库
 '====================================================
 set rs=server.CreateObject("adodb.recordset")
 rs.open "select top 1 * from news order by id desc",conn,3,3
 rs.addnew
 rs("NewsClass")=NewsClass
 rs("City")=City
 rs("Position")=Position
 rs("HouseType")=HouseType
 rs("Level")=Level
 rs("Area")=Area
 rs("Price")=Price
 rs("Demostra")=Demostra
 rs("ContactMan")=ContactMan
 rs("Contact")=Contact
 rs.update
 rs.close
 set rs=nothing
 end if
 '==================================================
 
next
function RemoveTag(body)
 Set regEx = New RegExp
 regEx.Pattern = "<[a].*?<\/[a]>"
 regEx.IgnoreCase = True
 regEx.Global = True
 Set Matches = regEx.Execute(body)
 dim i,arr(15),ifexit
 i=0
 j=0
 For Each Match in Matches
  TempStr = Match.Value 
  TempStr=replace(TempStr,"<td>","")
  TempStr=replace(TempStr,"</td>","")
  TempStr=replace(TempStr,"<tr>","")
  TempStr=replace(TempStr,"</tr>","") 
  arr(i)=TempStr 
  i=i+1
  if(i>=15) then
   exit for
  end if
 Next
 Set regEx=nothing
 Set Matches =nothing
 RemoveTag=arr
 
end function
function RegexHtml(body)
 dim r_arr(47),r_temp
 Set regEx2 = New RegExp
 regEx2.Pattern ="<a.*?<\/a>"
 regEx2.IgnoreCase = True
 regEx2.Global = True
 Set Matches2 = regEx2.Execute(body)
 iii=0
 For Each Match in Matches2
 
  r_arr(iii)=Match.Value
 
  iii=iii+1 
 Next
 RegexHtml=r_arr
 set regEx2=nothing
 set Matches2=nothing
end function
'======================================================
conn.close
set conn=nothing
%>
</body>
</html>
 

  function.asp
 <%
'**************************************************
'函数名:gotTopic
'作  用:截字符串,汉字一个算两个字符,英文算一个字符
'参  数:str   ----原字符串
'       strlen ----截取长度
'返回值:截取后的字符串
'**************************************************
function gotTopic(str,strlen)
 if str="" then
  gotTopic=""
  exit function
 end if
 dim l,t,c, i
 str=replace(replace(replace(replace(str,"&nbsp;"," "),"&quot;",chr(34)),"&gt;",">"),"&lt;","<")
 str=replace(str,"?","")
 l=len(str)
 t=0
 for i=1 to l
  c=Abs(Asc(Mid(str,i,1)))
  if c>255 then
   t=t+2
  else
   t=t+1
  end if
  if t>=strlen then
   gotTopic=left(str,i) & "…"
   exit for
  else
   gotTopic=str
  end if
 next
 gotTopic=replace(replace(replace(replace(gotTopic," ","&nbsp;"),chr(34),"&quot;"),">","&gt;"),"<","&lt;")
end function
'=========================================================
'函数:RemoveHTML(strHTML)
'功能:去除HTML标记
'参数:strHTML  --要去除HTML标记的字符串
'=========================================================
Function RemoveHTML(strHTML)
Dim objRegExp, Match, Matches
Set objRegExp = New Regexp
objRegExp.IgnoreCase = True
objRegExp.Global = True
'取闭合的<>
objRegExp.Pattern = "<.+?>"
'进行匹配
Set Matches = objRegExp.Execute(strHTML)
' 遍历匹配集合,并替换掉匹配的项目
For Each Match in Matches
strHtml=Replace(strHTML,Match.Value,"")
Next
RemoveHTML=strHTML
Set objRegExp = Nothing
set Matches=nothing
End Function
%>
 

  conn.asp
 <%
'on error resume next
set conn=server.CreateObject("adodb.connection")
con= "driver={Microsoft Access Driver (*.mdb)};dbq=" & Server.MapPath("stest.mdb")
conn.open con
sub connclose
   conn.close
   set conn=nothing  
end sub
%>
 

  附:抓取信息的详细页面事例
总序列号:
479280  
信息类别:
出租
所在城市:
济南
房屋具体位置:
华龙路华信路交界口
房屋类型:
其他
楼层:
六层
使用面积:
24~240 平方米之间
房价:
0  [租赁:元/月,买卖:万元/套]
其他说明:
华信商务楼3至6层小空间对外出租(0.5元/平起),本楼属纯商务办公投资使用,可用于办公写字间,周边设施齐全、交通便利(37、80、K95在本楼前经过),全产权、市证,楼内设施包括水、电、暖、电梯设施齐全,有意者可电讯!
联系人:
鲁、王
联系方式:
88017966、86812217
信息来源:
2005-8-4 8:28:55  来自:218.98.86.175
点击次数:
19

ASP上两个防止SQL注入式攻击Function
'==========================
'过滤提交表单中的SQL
'==========================
function ForSqlForm()
 dim fqys,errc,i,items
 dim nothis(18)
 nothis(0)="net user"
 nothis(1)="xp_cmdshell"
 nothis(2)="/add"
 nothis(3)="exec%20master.dbo.xp_cmdshell"
 nothis(4)="net localgroup administrators"
 nothis(5)="select"
 nothis(6)="count"
 nothis(7)="asc"
 nothis(8)="char"
 nothis(9)="mid"
 nothis(10)="'"
 nothis(11)=":"
 nothis(12)=""""
 nothis(13)="insert"
 nothis(14)="delete"
 nothis(15)="drop"
 nothis(16)="truncate"
 nothis(17)="from"
 nothis(18)="%"
 
 'nothis(19)="@" 
 errc=false
 for i= 0 to ubound(nothis)
  for each items in request.Form
  if instr(request.Form(items),nothis(i))<>0 then
   response.write("<div>")
   response.write("你所填写的信息:" & server.HTMLEncode(request.Form(items)) & "<br>含非法字符:" & nothis(i))
   response.write("</div>")
   response.write("对不起,你所填写的信息含非法字符!<a href=""#"" onclick=""history.back()"">返回</a>")
   response.End()
  end if
  next
 next
end function
'==========================
'过滤查询中的SQL
'==========================
function ForSqlInjection()
 dim fqys,errc,i
 dim nothis(19)
 fqys = request.ServerVariables("QUERY_STRING")
 nothis(0)="net user"
 nothis(1)="xp_cmdshell"
 nothis(2)="/add"
 nothis(3)="exec%20master.dbo.xp_cmdshell"
 nothis(4)="net localgroup administrators"
 nothis(5)="select"
 nothis(6)="count"
 nothis(7)="asc"
 nothis(8)="char"
 nothis(9)="mid"
 nothis(10)="'"
 nothis(11)=":"
 nothis(12)=""""
 nothis(13)="insert"
 nothis(14)="delete"
 nothis(15)="drop"
 nothis(16)="truncate"
 nothis(17)="from"
 nothis(18)="%"
 
 nothis(19)="@" 
 errc=false
 for i= 0 to ubound(nothis)
 if instr(FQYs,nothis(i))<>0 then
 errc=true
 end if
 next
 if errc then
 response.write "查询信息含非法字符!<a href=""#"" onclick=""history.back()"">返回</a>"
 response.end
 end if
end function
ASP防SQL注入攻击程序
  SQL注入被那些菜鸟级别的所谓黑客高手玩出了滋味,发现现在大部分黑客入侵都是基于SQL注入实现的,哎,谁让这个入门容易呢,好了,不说废话了,现在我开始说如果编写通用的SQL防注入程序一般的http请求不外乎get 和 post,所以只要我们在文件中过滤所有post或者get请求中的参数信息中非法字符即可,所以我们实现http 请求信息过滤就可以判断是是否受到SQL注入攻击。
  IIS传递给asp.dll的get 请求是是以字符串的形式,,当 传递给Request.QueryString数据后,asp解析器会分析Request.QueryString的信息,,然后根据"&",分出各个数组内的数据所以get的拦截如下:
  首先我们定义请求中不能包含如下字符:
|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare
 
各个字符用"|"隔开,,然后我们判断的得到的Request.QueryString,具体代码如下 :
dim sql_injdata
SQL_injdata = "'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare"
SQL_inj = split(SQL_Injdata,"|")
If Request.QueryString<>"" Then
 For Each SQL_Get In Request.QueryString
  For SQL_Data=0 To Ubound(SQL_inj)
   if instr(Request.QueryString(SQL_Get),Sql_Inj(Sql_DATA))>0 Then
    Response.Write "<Script Language=****>alert('天下电影联盟SQL通用防注入系统提示↓nn请不要在参数中包含非法字符尝试注入!');history.back(-1)</Script>"
    Response.end
   end if
  next
 Next
End If

这样我们就实现了get请求的注入的拦截,但是我们还要过滤post请求,所以我们还得继续考虑request.form,这个也是以数组形式存在的,我们只需要再进一次循环判断即可。代码如下:
If Request.Form<>"" Then
 For Each Sql_Post In Request.Form
  For SQL_Data=0 To Ubound(SQL_inj)
   if instr(Request.Form(Sql_Post),Sql_Inj(Sql_DATA))>0 Then
    Response.Write "<Script Language=****>alert('天下电影联盟SQL通用防注入系统提示↓nn请不要在参数中包含非法字符尝试注入!nnHTTP: //www.521movie.com ');history.back(-1)</Script>"
    Response.end
   end if
  next
 next
end if

好了大功告成,我们已经实现了get和post请求的信息拦截,你只需要在conn.asp之类的打开数据库文件之前引用这个页面即可。放心的继续开发你的程序,不用再考虑是否还会受到SQL注入攻击。难道不是么?
xhtml validator Powered by CVB 5.0.2 (c) 2005 cnvery.net.
Processed in 156.25 ms, 2 queries.
GotoTop XClose