04SQL注入原理与实践

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 【1月更文挑战第5天】给单位零基础小伙伴准备的网安入门教程,本教程是基于蚁景实验室搭建,基于自建虚拟机搭建需自行准备前置环境,04SQL注入原理与实践 ,请遵守网络安全法!请遵守网络安全法!请遵守网络安全法!请勿破坏公共网络网络安全!

预备知识

什么是SQL注入?

所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。

我该如何向非技术人解释SQL注入?:

https://security.stackexchange.com/questions/25684/how-can-i-explain-sql-injection-without-technical-jargon

PHP基础语法:

https://www.w3cschool.cn/php/

MySQL基础语法:

https://www.w3cschool.cn/mysql/

mysql创建表时反引号的作用:

https://www.cnblogs.com/nmap/p/6714031.html

实验目的

掌握SQL注入的原理,对于简单的SQL注入点,能够通过注入获取数据。

实验步骤一

在学习这个实验请确保已经掌握了“SQL注入中information_schema的作用”实验中的内容。

在开始本次实验前,请先查看预备知识中的链接。文中有关于SQL注入比较形象的说明。

本次实验就来通过PHP代码来实例分析SQL注入,本系列实验使用的数据库是MySQL。

本次实验来学习可联合查询的注入(即union注入),为了方便,我们选择通过GET方式来传参。如果不知道如何给网页传参,不知道服务器如何获取用户传过去的参数的话,可以学习“获取网页参数”这个实验。

本实验的源码保存在c:\wamp\www\sqli 目录下。

浏览器打开sqli.com/sqli-1.php。

image.png

其源码如下:

image.png

代码已经写了注释,如果没有给这个页面传参数,则默认传一个id参数,它的值为1。可以看到,在13行,获取到用户传过来的参数后,直接进入了SQL语句,带进了查询语句,没有任何其他操作,很明显的存在SQL注入。在sql语句中,new被反引号包起来了,关于反引号的作用,请参考预备知识中的“mysql创建表时反引号的作用”。以前很多的网站的信息公告页面的代码与上面类似,不过现在一般都是用的MVC框架,更加模块化,这里先不说MVC是什么,会在以后的课程里介绍,不知道MVC也完全不影响本次实验。

在网上搜到的判断网站是否存在注入点最常见的是加单引号,即“’“,如果不加单引号页面显示正常,而加了单引号以后,页面显示不正常或者错误,则说明网页存在SQL注入,还有一种就是如果加and 1=1 页面显示正常,加and 1=2页面不正常或者错误,同样说明存在SQL注入,这是什么原因呢?首先通过这个方法来判断是否存在注入点。

先在URL后面加一个单引号,可以看到页面报错了,这个警告的意思是:mysql_fetch_array()这个函数第一个参数期望的参数类型是一个资源集,但是给的是一个布尔值,出现该警告的位置在代码的第15行。

image.png

查看代码,发现它的第一个参数$result这个参数的值来自第14行,它是mysql_query执行后的返回值。

image.png

查看php官方手册,可以看到mysql_query在查询出错的情况下会返回false,还有一种情况就是在没有权限访问查询语句中引用的表的时候,也会返回false。

image.png

这里明显不会是第二种情况,因为我们没有输入单引号的时候,能正常查询,而我们又没有修改查询的表,所以排除这种情况。所以可能就是前面的语句在MySQL里执行出错了,于是返回了false,这说明我们传进去的参数1’破坏了SQL语句,我们可以稍微修改下代码,在第14行后面输出一下当前执行的sql语句。修改后的代码如下:

image.png

然后再次访问页面,输出了数据库最终执行的SQL语句,为:select * from new where id = 1',有编程经验的可能一眼就能看出来该SQL语句有错误,因为如果单引号或者双引号不是出现在字符串中的时候,单引号、双引号都是成对出现的,SQL数据库将单引号解析成代码与数据间的分界线,在单引号外面的内容是需要运行的代码,而单引号引起来的内容都是数据。

image.png

我们可以直接复制该语句到MySQL中去执行。由于数据库编码是utf8的,直接在mysql客户端中进行查询,中文会显示乱码,所以可以到phpmyadmin中来执行这个sql语句。

访问http://localhost/phpmyadmin/ ,如果需要输入密码,账号输入root,密码为空,然后点击执行登录。

image.png

然后点击左边的sqli,在右侧的new这一行选择浏览。

image.png

再选择SQL。

image.png

复制刚才输出的语句:select * from new where id = 1',然后点击执行。

image.png

返回的错误很明显,引号不配对,语句执行出错,所以mysql_query返回了false,出现这个错误是因为单引号被解析成了字符串分隔符,运行时执行的SQL查询在语法上存在错误,所以数据库抛出异常。

image.png

这说明我们输入的参数被mysql服务器当作SQL命令执行了!如果是这样的话,那我们是不是可以输入其他字符让数据库执行然后返回我们想要知道的数据呢?

再来看下通过and 1=1和and 1=2来判断网页是否存在SQL注入的原理。

首先传个1 and 1=1,页面显示正常,而且最终执行的SQL语句是: select * from new where id = 1 and 1=1

image.png

再次尝试1 and 1=2,页面除了输出最终执行的SQL页面,没有其他任何输出。

image.png

为什么会这样?就算SQL语句执行出错,也应该像上面那样报错不是吗?

其实这里SQL语句执行并没有出错,问题出在and 1=2上,再来一下这条语句,它从new这个表里面查询数据,但是有限制条件,where指查询满足后面的数据,也就是说需要查找id = 1的数据,并且需要 1=2,但是1=2这是用于不可能满足的。所以,这个语句被数据库准确无误地执行了,但是它并没有找到符合条件的数据,所以没有任何数据输出。而前面加 1 and 1=1能正常返回数据,是因为1=1这个永远为真,所以这个条件可以说是跟没加一样。

继续去phpmyadmin里验证,分别执行这2条语句。

image.png

可以看到,在后面加and 1=1的时候,返回了id=1的数据。然后执行and 1=2,点击显示查询框来重新输入SQL语句。

image.png

然后输入select * from new where id = 1 and 1=2,点击执行。

image.png

可以看到提示返回的查询结果为空,也就是没有返回结果。但是在下面还是显示了一条结果,这是为什么呢? 其实这是上一条的查询,如果不信的,可以把id改成2试试。

image.png

可以看到我们虽然查询语句中的id变成了2,但是下方还是1,说明这不是我们这次查询的结果。

现在理解上面2种方法来判断页面是否存在注入的原理了吗?

通过添加单引号来判断页面是否存在SQL注入,是因为我们添加的单引号被传到了SQL语句中,破坏了原本的SQL语句,还造成了语法错误,所以SQL语句执行,页面返回跟正常的时候会有不同。

而通过and 1=1 、 and 1=2来判断页面是否存在注入,是因为我们修改了原本的SQL语句逻辑,当添加and 1=1的时候,这个条件永远成立,所以页面一定返回正常(需要该页面存在注入),但是当添加and 1=2的时候,这个条件永远不成立,所以如果该页面存在注入,必然不会返回任何数据。所以就会说,如果添加and 1=1页面返回正常,添加and 1=2页面返回不正常或者错误,就说明页面存在SQL注入。当然这只能大概判断,而不是说明该页面一定存在注入,其他情况在后面的实验里说。

提交的参数,改变了原来SQL语句的含义,并且被服务器当成SQL语句执行了,这就是SQL注入!

那万能密码又是怎么回事呢? 网上找到的万能密码都是类似’ or 1=1这种,为什么输入这个字符串就可以绕过登录了呢? 我们也用or 1=1试试,看在这个页面提交这个值是什么效果。

访问

http://sqli.com/sqli-1.php?id=1or1=1

image.png

发现居然输出了多条记录,这里其实输出了new表中所有的数据,所有的建表语句都在sql.sql文件中,可以打开看下sqli数据库中有哪些表,有什么内容。

那么为什么这里会输出所有内容呢?

最终执行的SQL语句是

select * from `new` where id = 1 or 1=1

它这里只要满足id =1 或者1=1任意一个条件,而1=1永远为真,所以返回了所有的数据,其效果与select * from new一样。

实验步骤二

但是如果仅仅只是读取new这个表里面的数据,对我们来说,其实意义不大,因为即使不存在注入,我们也可以增加ID的值来查看其中所有的信息。比如访问http://sqli.com/sqli-1.php?id=2 可以查看id=2的内容。

image.png

我们希望的是能够通过注入,获取一些网站管理员不希望我们知道的数据,比如管理员的账号密码。

在本页面的源码中,注入点在where后面,也就说,从哪个表中查询什么数据是写死的,那么怎么才能通过注入获取其他表中的内容呢? 比如获取user表中的数据。

通过union操作符就可以达到我们的目的,union可以合并两条或者多条select语句的查询结果,它的语法如下:

Select column-1,column-2,,column-N from table-1 union select column-1,column-2,,column-N from table-2

它的返回值是两个select语句查询结果组成的表。我们可以通过在第一个查询后面注入一个union运算符,并添加另外一个任意查询,就可以读取到数据库中用户可以访问的任何表。但是,使用union有一些限制:

  • 两个查询返回的列数必须型相同。

  • 两个select语句对应列所返回的数据类型必须是相同或者是兼容的。

两个查询返回的列数必须相同时什么意思呢?

是指当前的两个select 他们查询的列的个数必须一致,如果第一个select查询了5列,则第二个select也必须查询5列。

如:

select title, content from new union select username, password from user;

像上面的查询,列数相同,会返回这2个查询的结果集。

来到phpmyadmin中验证一下,如图:

image.png

但是如果列数不同,如:

select title, content from new union select username from user;

则会报错,如图:

image.png

很明显的提示查询的列数不同。

那么第二个条件又是什么意思呢?

它的意思是,第一个查询的每一列,与第二个查询的对应的列的数据类型,至少应该是兼容的。比如,字符串是兼容数字的。但是数字是不兼容一些字母等字符串的,所以,如果字段的类型是int,但是在往该字段插入字符串数据的时候,就会报错。但是在union查询的时候,其实这个限制可以忽略不计,几乎所有类型都兼容。

同样来到phpmyadmin中测试,这里只测试常见的类型,有兴趣的可以自行测试所有的类型。执行以下SQL语句:

SELECT id, title, content FROM `new` union select id, username, password from user

返回结果正常。

image.png

查看sql.sql发现new 表中的title字段是text,但是user表中的password字段是char,明显这2个查询的对应列的类型不同,但为什么查询还是没报错呢? 因为text类型是兼容char类型的。

为了方便比较,现在我们稍微修改一下SQL语句,只查询2列,但是有一列的类型不兼容,第一个查询的第一列类型为int,但第二个查询的第一列类型为char,修改后的语句如下:

SELECT id, title FROM `new` union select username, password from user

执行后同样没报错,因为int和char同样是兼容的!

image.png

实际的SQL注入应用中,一般第二个select都是用数字或者null,因为这2个类型兼容比较,null更是兼容所有类型。

所以我们这里重点关注怎么知道查询中列的数量,代码中,写的是select * from new,直接在代码中看不出来new这个表中有多少列,而需要去查看建表语句,而在实际应用中,除非是开源的CMS,否则你不可能准确知道它查询了多少列,这就需要我们想个办法来获取当前查询的列数。

一个简单的办法是通过order by 子句来确定。Order by 是根据指定的列名进行排序。

Order by 子句可以接受一个列名作为参数,也可以接受一个简单的、能表示特定列的数字,所以可以通过增大order by 子句中代表列的数字来识别查询中的列数。

来到phpmyadmin测试。

执行show create table new来查看建表语句

image.png

如果像下面这样显示不完整

image.png

可以点击选项,选中完整内容。

image.png

再次执行即可。

可以看到这个表有3列,然后来测试用order by子句来测试列数量,从1开始,每次查询加1,加到报错为止,如:

1的时候正常,继续增加该值。

image.png

2的时候正常,然后继续增加该值,到4的时候,发现执行出错。

image.png

因为这里一共只有3列,但是你要根据第4列来进行排序,当然就会报错了。

再测试一个语句,把* 改成title, content。还是从1开始测试。结果如下:

select title, content from new order by 1

结果正常。

image.png

select title, content from new order by 2

结果正常。

image.png

select title, content from new order by 3

报错。

image.png

因为我们这里只查询了2列。

有了以上知识,我们就可以在不看源码,不看建表语句的情况下,判断当前查询的语句中包含多少列了。

现在就来注入页面进行测试。

访问http://sqli.com/sqli-1.php?id=1 order by 1,页面正常。

image.png

访问http://sqli.com/sqli-1.php?id=1 order by 2,页面正常。

image.png

依次增加order by 子句后面的值,直到4的时候,页面报错。

image.png

所以我们可以得出结论,在这个查询中,一共查询了3列,因为4的时候报错了。

然后就可以通过union 来进行查询user表中的数据啦。

根据union的语法,构造注入语句,通过前面的测试已经知道这个查询一共查询了3列,在符合union操作符的前提下,可以构造如下语句:

http://sqli.com/sqli-1.php?id=1 union select null, null, null

访问该连接,页面正常,没有任何多余的内容出现,与没加后面的sql语句一样。但是你查看源码会发现,多了个h2标签和p 。

image.png

因为其实我们这里后面的查询也执行,只是返回的是null,所以在页面没有显示,但是标签还是被数出来了!

虽然后面的语句执行了,但是如何获取我们想要的数据呢?

这就需要我们确定哪个列最终会被输出。所以我们可以把null依次替换成数字或者其他字符。

例如:

http://sqli.com/sqli-1.php?id=1 union select 1,2,3

可以看到页面输出2,3,这就说明在前一个查询中,第二列和第三列被输出来了,我们也可以依次替换而不是一次就全部替换成数字,像下面这样:

http://sqli.com/sqli-1.php?id=1 union select 1, null, null
http://sqli.com/sqli-1.php?id=1 union select null, 2, null
http://sqli.com/sqli-1.php?id=1 union select null, null, 3

其中 1、2、3都可以替换成其他数字,需要注意的是,替换成数字以外的字符的时候,字符需要用双引号或者单引号引起来,否则就是SQL语法错误了。

如:

http://sqli.com/sqli-1.php?id=1 union select “test”,”test2”,”test3”

image.png

在第二个select中,如果该列被原样输出了,说明在该列可以用来获取信息,因为通过该列获取的信息会被程序输出。那么为什么会这样呢?

这是因为mysql的select 在直接select一个字符串常量或者数字的时候,会直接返回。这个也可以phpmyadmin中测试。

image.png

注意看查询的字符串与返回值的位置。

通过上面的方法确定输出位置以后,我们就可以用来获取数据啦!

我们可以执行一些数据库函数,如:执行database()来查看当前数据库,执行user()来查看当前连接数据库的用户。

image.png

我们的目标是获取user表中的用户名和密码,查看sql.sql文件,可以看到user表中存在username, password字段

image.png

所以就可以构造如下语句:

http://sqli.com/sqli-1.php?id=1 union select null, username, password from user

image.png

这样就获取了user表中所有的用户名和密码。

如果你写的网站存在注入,别人很容易就能通过SQL注入拿到管理员账号密码,那么网站就很容易被人篡改,并且导致信息泄露。

实验步骤三

在实验步骤二中,是通过查看建表语句知道表中存在什么字段的,那么如何在不知道建表语句的情况下,通过注入来获取当前连接数据库的账号所有有权限访问的数据库名、表名以及字段呢?

这就需要了解mysql数据库的information_schema 这个数据库了。可以参考“SQL注入中information_schema的作用”实验。

根据从“SQL注入中information_schema的作用”实验提到的技术,我们可以很容易就构造出获取所有数据库的语句,为:

http://sqli.com/sqli-1.php?id=1 union select 1,schema_name,3 from information_schema.schemata。

可以看到返回了所有的数据库名:

image.png

其中schema_name 和 数字3的位置可以互换,没有什么影响,因为这里只需要有一个位置输出了就行,其中的数字1和3 可以被其他数字或者字符或者NULL代替,用字符代替的时候,记得用双引号或者单引号引上。虽然1和3可以被代替,但是不能缺少,因为必须要保持3列union才能正确执行。

这里后面的from 为什么是information_schema.schemata而不是schemata呢?

因为在当前执行SQL语句的环境中,它的默认是库是sqli,如果我们要跨库查询,则需要在表名前加上库名,如果不加上库名,则表示在sqli这个数据库的schemata表中查询,由于sqli这个数据库不存在schemata表,所以会报错,如下图:

image.png

如果我们输出mysql 的报错信息,就可以看到很明显的提示。

修改sqli-1.php源文件,在执行sql语句的下面加入如下代码:

if(!$result){
   
        

        die(mysql_error());

    }

修改后内容为:

image.png

再次访问上述链接:

image.png

提示表sqli.schemata 不存在。

通过前面的注入语句,我们已经获取了所有的数据库库名:

information_schema

mysql

performance_schema

sqli

test

在实验步骤二中,我们已经获取了sqli数据库user表中的数据,这次换一个,改成mysql。mysql这个数据库保存了mysql的账号密码信息,在注入的时候,可以读取该表中的数据来读取mysql账号密码。

现在就通过注入来获取mysql的账号和密码。

首先查看mysql这个数据库中有哪些表。

构造如下语句:

1 union select 1, table_name,3 from information_schema.tables where table_schema='mysql'

返回结果如下:

image.png

可以看到有很多表,由于这里表太多,不再截取所有表的图片,拉动浏览器右边的滚动条到最下面,可以看到存在一个user表。

image.png

这个表中保存了mysql服务器的账号和密码的hash值。然后构造语句获取该表中的所有列名。构造语句为:

1 union select 1, column_name, 3 from information_schema.columns where table_name ='user' and table_schema='mysql'

访问后返回该表中所有的列名。

image.png

存在User字段和Password字段。

注:列名也就是我们常说的字段,他们指的是一个东西。

User字段保存了MySQL服务器的用户名,Password字段保存的是用户的Hash值。

由于在这里有2个位置可以输出,所以我们可以一次查询用户的账号和密码。

构造语句如下:

1 union select 1, User, Password from mysql.user

image.png

发现页面只有输出root。是我们查询失败了么?

查看一下页面源码,把下方滚动条拉到最右方,发现有多余的标签。

image.png

这说明确实有输出,这里之所以会这样是因为我们的root密码为空,所以页面显示看不出来。

进入phpmyadmin确认一下。

image.png

在phpmyadmin中显示有3条,这跟我们上面查的不同。

进入mysql终端看一下,到底有多少条记录。

点击右下角的wampserver图标,然后在弹出来的列表中点击MySQL,再选择MySQL控制台。

image.png

会弹出一个黑框,这就是mysql客户端,此时要求输入密码,由于root的密码为空,直接回车即可。

image.png

然后执行上述SQL语句。

image.png

在mysql终端里面查询显示了4条数据,但是为什么我们注入的时候只获取输出了2次呢?

这个问题是union导致的。union默认情况下会消去表中重复行,所以这里的3个root的行只显示了一次,还有一条记录为空也显示一次。所以我们看到后面有2个多余的

标签。那么,如果我们要查询重复的值怎么办呢?

只要早union 后面加一个all即可,当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行。

在注入语句中的union后添加一个all,构造的注入语句为:

1 union all select 1, User, Password from mysql.user

再次提交。

image.png

输出了3个root,查看源码可以看到多余的4个h2以及p标签。

image.png

最后一个h2标签的内容为空,是因为在mysql.user中,存在一条空记录,可以查看上面在终端执行sql语句的返回结果的截图,所以输出为空。

image.png

本次实验只演示获取mysql.user表中的User和Password字段的值,请自己尝试获取数据库中的一些数据。

课后问题:如果页面没有输出的地方,如何通过SQL注入获取信息?

即使一个网页没有直接输出数据库查询结果的地方,攻击者仍然可能通过SQL注入漏洞获取信息,这通常涉及以下几种方法:

  • 错误消息泄露:

SQL注入攻击时,可以通过构造特定的SQL语句导致数据库返回错误。这些错误消息有时会包含有关数据库结构、表名或列名等敏感信息。

  • 盲注(Blind SQL Injection):

当页面不显示任何数据库内容时,攻击者可以利用布尔型盲注,通过改变查询逻辑使页面返回不同的状态来判断条件是否成立。例如,通过更改WHERE子句使得查询应该返回0行或非0行,根据页面加载时间的变化、HTTP响应代码的不同或其他间接反馈来推断数据。

  • 时间延迟注入:

如果服务器端执行的SQL语句对注入的数据有延时反应(如SLEEP()函数),则可以根据延时长短来判断某个条件是否为真,以此逐字逐位地提取数据。

  • 联合查询注入(Union-based SQL Injection):

在某些情况下,即使原始页面设计并未展示所有查询结果,攻击者仍可能通过注入UNION操作符与其他查询结果集合并,迫使服务器将额外的数据作为页面的一部分输出。

  • 存储过程和OUT参数:

攻击者可能会利用注入调用存储过程,并使用OUT参数将数据写入数据库的其他位置,然后通过其他方式读取这些数据。

  • 二进制日志泄漏:

在极端情况下,恶意SQL注入可能触发MySQL服务器的二进制日志记录,而这些日志在某些配置下可能是可访问的,攻击者可以从日志中提取执行过的SQL命令及其结果。

总之,即使没有明显的输出途径,只要存在SQL注入漏洞,攻击者就有办法绕过正常的输出机制,通过各种间接手段获取数据库中的敏感信息。解决此类问题的关键在于正确编写安全的SQL查询,采用预编译语句(PreparedStatement)并遵循最小权限原则来限制用户输入对数据库操作的影响。

参考资料

PHP中的超全局变量:https://php.net/manual/zh/language.variables.superglobals.php

PHP中预定义变量$_GET:https://php.net/manual/zh/reserved.variables.get.php

var_dump函数语法: https://php.net/manual/zh/function.var-dump.php

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
SQL 存储 数据库
SQL实践篇(二):为什么微信用SQLite存储聊天记录
SQL实践篇(二):为什么微信用SQLite存储聊天记录
66 1
|
1月前
|
存储 SQL Web App开发
SQL实践篇(一):使用WebSQL在H5中存储一个本地数据库
SQL实践篇(一):使用WebSQL在H5中存储一个本地数据库
47 2
|
3月前
|
SQL 测试技术 项目管理
轻松学习SQL外键约束的核心原理和实用技巧
轻松学习SQL外键约束的核心原理和实用技巧
48 0
|
4月前
|
SQL HIVE
Hive sql 执行原理
Hive sql 执行原理
43 0
|
5天前
|
SQL 分布式计算 资源调度
一文解析 ODPS SQL 任务优化方法原理
本文重点尝试从ODPS SQL的逻辑执行计划和Logview中的执行计划出发,分析日常数据研发过程中各种优化方法背后的原理,覆盖了部分调优方法的分析,从知道怎么优化,到为什么这样优化,以及还能怎样优化。
|
8天前
|
SQL 自然语言处理 数据库
NL2SQL实践系列(2):2024最新模型实战效果(Chat2DB-GLM、书生·浦语2、InternLM2-SQL等)以及工业级案例教学
NL2SQL实践系列(2):2024最新模型实战效果(Chat2DB-GLM、书生·浦语2、InternLM2-SQL等)以及工业级案例教学
NL2SQL实践系列(2):2024最新模型实战效果(Chat2DB-GLM、书生·浦语2、InternLM2-SQL等)以及工业级案例教学
|
11天前
|
SQL 自然语言处理 测试技术
NL2SQL进阶系列(4):ConvAI、DIN-SQL等16个业界开源应用实践详解[Text2SQL]
NL2SQL进阶系列(4):ConvAI、DIN-SQL等16个业界开源应用实践详解[Text2SQL]
NL2SQL进阶系列(4):ConvAI、DIN-SQL等16个业界开源应用实践详解[Text2SQL]
|
15天前
|
SQL 人工智能 自然语言处理
NL2SQL进阶系列(2):DAIL-SQL、DB-GPT开源应用实践详解Text2SQL
NL2SQL进阶系列(2):DAIL-SQL、DB-GPT开源应用实践详解Text2SQL
NL2SQL进阶系列(2):DAIL-SQL、DB-GPT开源应用实践详解Text2SQL
|
15天前
|
SQL 监控 数据库
数据库管理与电脑监控软件:SQL代码优化与实践
本文探讨了如何优化数据库管理和使用电脑监控软件以提升效率。通过SQL代码优化,如使用索引和调整查询语句,能有效提高数据库性能。同时,合理设计数据库结构,如数据表划分和规范化,也能增强管理效率。此外,利用Python脚本自动化收集系统性能数据,并实时提交至网站,可实现对电脑监控的实时性和有效性。这些方法能提升信息系统稳定性和可靠性,满足用户需求。
52 0
|
1月前
|
SQL 存储 NoSQL
SQL实践篇(三):什么是Redis
SQL实践篇(三):什么是Redis
24 1