• [其他] MySQL慢查询之慢 SQL 定位、日志分析与优化方案
     为何要对慢SQL进行治理 每一个SQL都需要消耗一定的I/O资源,SQL执行的快慢直接决定了资源被占用时间的长短。假设业务要求每秒需要完成100条SQL的执行,而其中10条SQL执行时间过长,从而导致每秒只能完成90条SQL,所有新的SQL将进入排队等待,直接影响业务,然后用户就各种投诉来了。  治理的优先级 master数据库->slave数据库 采用读写分离架构,读在从库slave上执行,写在主库master上执行。但由于从库的数据都是在主库复制过去的,主库如果等待较多的情况,会加大从库的复制延时 执行SQL次数多的优先治理 某张表被高并发集中访问的优先治理 MySQL执行原理 为了更好的优化慢SQL,我们来简单了解下MySQL的执行原理    绿色部分为SQL实际执行部分,主要分为两步:  解析:词法解析->语法解析->逻辑计划->查询优化->物理执行计划,过程中会检查缓存是否可用,如果没有可用缓存则进入下一步mysql_execute_command执行 执行:检查用户、表权限->表加上共享读锁->取数据到query_cache->取消共享读锁 如何发现慢查询SQL -- 修改慢查询时间,只能当前会话有效; set long_query_time=1; ­ -- 启用慢查询 ,加上global,不然会报错的; set global slow_query_log='ON';­­  -- 是否开启慢查询; show variables like "%slow%";­­  -- 查询慢查询SQL状况; show status like "%slow%"; ­­  -- 慢查询时间(默认情况下MySQL认位10秒以上才是慢查询) show variables like "long_query_time"; ­­   除了sql的方式,我们也可以在配置文件(my.ini)中修改,加入配置时必须要在[mysqld]后面加入  -- 开启日志; slow_query_log = on -- 记录日志的log文件(注意:window上必须写绝对路径) slow_query_log_file = D:/mysql5.5.16/data/showslow.log -- 最长查询的秒数; long_query_time = 2 -- 表示记录没有使用索引的查询 log­queries­not­using­indexes ­­   特别注意:开启慢查询会带来CPU损耗与日志记录的IO开销,所以建议间断性的打开慢查询日志来观察MySQL运行状态 慢查询分析示例 假设我们有一条SQL  SELECT * FROM `emp` where ename like '%mQspyv%';   执行时间为1.163s,而我们设置的慢查询时间为1s,这时我们可以打开慢查询日志进行日志分析:  ## Time: 150530 15:30:58 ­­ -- 该查询发生在2015­5­30 15:30:58 ## User@Host: root[root] @ localhost [127.0.0.1] ­­ --是谁,在什么主机上发生的查询 ## Query_time: 1.134065 Lock_time: 0.000000 Rows_sent: 8 Rows_examined: 4000000 Query_time: --查询总共用了多少时间,Lock_time: 在查询时锁定表的时间,Rows_sent: 返回多少rows数据,Rows_examined: 表扫描了400W行数据才得到的结果;  如果我们的慢SQL很多,人工分析肯定分析不过来,这时候我们就需要借助一些分析工具,MySQL自带了一个慢查询分析工具mysqldumpslow,以下是常见使用示例  mysqldumpslow ­s c ­t 10 /var/run/mysqld/mysqld­slow.log # 取出使用最多的10条慢查询 mysqldumpslow ­s t ­t 3 /var/run/mysqld/mysqld­slow.log # 取出查询时间最慢的3条慢查询 mysqldumpslow ­s t ­t 10 ­g “left join” /database/mysql/slow­log #得到按照时间排序的前10条里面含有左连接的查询语句 mysqldumpslow ­s r ­t 10 ­g 'left join' /var/run/mysqld/mysqldslow.log # 按照扫描行数最多的  SQL语句常见优化 只要简单了解过MySQL内部优化机制,就很容易写出高性能的SQL 不使用子查询  SELECT * FROM t1 WHERE id (SELECT id FROM t2 WHERE name='hechunyang');  在MySQL5.5版本中,内部执行计划器是先查外表再匹配内表,如果外表数据量很大,查询速度会非常慢  再MySQL5.6中,有对内查询做了优化,优化后SQL如下  SELECT t1.* FROM t1 JOIN t2 ON t1.id = t2.id;  但也仅针对select语句有效,update、delete子查询无效,所以生成环境不建议使用子查询  避免函数索引  SELECT * FROM t WHERE YEAR(d) >= 2016;  即使d字段有索引,也会全盘扫描,应该优化为:  SELECT * FROM t WHERE d >= '2016-01-01';  使用IN替换OR  SELECT * FROM t WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30;  非聚簇索引走了3次,使用IN之后只走一次:  SELECT * FROM t WHERE LOC_IN IN (10,20,30);  LIKE双百分号无法使用到索引  SELECT * FROM t WHERE name LIKE '%de%';  应优化为右模糊  SELECT * FROM t WHERE name LIKE 'de%';  增加LIMIT M,N 限制读取的条数  避免数据类型不一致  SELECT * FROM t WHERE id = '19';  应优化为  SELECT * FROM t WHERE id = 19;  分组统计时可以禁止排序  SELECT goods_id,count(*) FROM t GROUP BY goods_id;  默认情况下MySQL会对所有GROUP BY co1,col2 …的字段进行排序,我们可以对其使用  ORDER BY NULL 点击并拖拽以移动 禁止排序,避免排序消耗资源  SELECT goods_id,count(*) FROM t GROUP BY goods_id ORDER BY NULL;  去除不必要的ORDER BY语句  总结 总的来说,我们知道曼查询的SQL后,优化方案可以做如下尝试:  SQL语句优化,尽量精简,去除非必要语句 索引优化,让所有SQL都能够走索引 如果是表的瓶颈问题,则分表,单表数据量维持在2000W(理论上)以内 如果是单库瓶颈问题,则分库,读写分离 如果是物理机器性能问题,则分多个数据库节点 
  • [其他] 索引最左前缀匹配原则
     索引最左前缀匹配原则 对于最左前缀匹配原则居然没有百度百科,实在是让我感觉不可思议。  最左前缀匹配原则,用几句话来概述就是: 顾名思义,就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。  什么是最左匹配原则? 最左前缀匹配原则,非常重要的原则,建立一个索引,对于索引中的字段,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。 =和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式  最左匹配原则实际场景及难点 如果只是上面这些概念的话,这篇博客显然是不合格的,那么接下来我们用实际场景来解释最左匹配原则的一些难点 先创建一张表  CREATE TABLE `student` (   `id` int(11) NOT NULL AUTO_INCREMENT,   `name` varchar(255) DEFAULT NULL,   `cid` int(11) DEFAULT NULL,   PRIMARY KEY (`id`),   KEY `name_cid_INX` (`name`,`cid`),   KEY `name_INX` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 1 2 3 4 5 6 7 8 注意上面的语句,在倒数第三行创建了name_cid_INX索引,包含name和cid字段 在倒数第二行创建了name_INX索引,包含name字段  执行1:  EXPLAIN SELECT * FROM student WHERE name=‘小红’;  结果:  依据mysql索引最左匹配原则,两个索引都匹配上了,这个没有问题。。  执行2:  EXPLAIN SELECT * FROM student WHERE cid=1;  结果:  执行3:  EXPLAIN SELECT * FROM student WHERE cid=1 AND name=‘小红’;   这个时候,对于初步了解最左前缀匹配原则的同学就会懵逼了,纳尼???  执行2,执行3不应该都与最左前缀匹配原则完全相悖吗?怎么还是使用了索引???(可以看到key字段中都表示用了name_cid_INX索引)顿时怀疑人生了有木有?  如果你也有跟上述一样的心理变化,说明你对索引的理解是狭隘的(没错,说的就是我。。。) 好的,接下来我们来揭秘了  上述,的两个查询的explain结果中显示用到索引的情况类型是不一样的。,可观察explain结果中的type字段。执行2和执行3中的type字段分别是: 执行2. type: index 执行3. type: ref (先去吃个饭,未完待续。。。)我回来啦,我们继续(自言自语好羞耻)  解释:  index:这种类型表示是mysql会对整个该索引进行扫描。要想用到这种类型的索引,对这个索引并无特别要求,只要是索引,或者某个复合索引的一部分,mysql都可能会采用index类型的方式扫描。但是呢,缺点是效率不高,mysql会从索引中的第一个数据一个个的查找到最后一个数据,直到找到符合判断条件的某个索引  所以:对于执行2:  EXPLAIN SELECT * FROM student WHERE   cid=1; 1 判断条件是cid=1,而cid是(name,cid)复合索引的一部分,没有问题,可以进行index类型的索引扫描方式。explain显示结果使用到了索引,是index类型的方式。  ref:这种类型表示mysql会根据特定的算法快速查找到某个符合条件的索引,而不是会对索引中每一个数据都进行一一的扫描判断,也就是所谓你平常理解的使用索引查询会更快的取出数据。而要想实现这种查找,索引却是有要求的,要实现这种能快速查找的算法,索引就要满足特定的数据结构。 简单说,也就是索引字段的数据必须是有序的,才能实现这种类型的查找,才能利用到索引。  有些了解的人可能会问,索引不都是一个有序排列的数据结构么。不过答案说的还不够完善,那只是针对单个索引,而复合索引的情况有些同学可能就不太了解了。  下面就说下复合索引: 以该表的(name,cid)复合索引为例,它内部结构简单说就是下面这样排列的:  mysql创建复合索引的规则是首先会对复合索引的最左边的,也就是第一个name字段的数据进行排序,在第一个字段的排序基础上,然后再对后面第二个的cid字段进行排序。其实就相当于实现了类似 order by name cid这样一种排序规则。 所以:第一个name字段是绝对有序的,而第二字段就是无序的了。所以通常情况下,直接使用第二个cid字段进行条件判断是用不到索引的,当然,可能会出现上面的使用index类型的索引。这就是所谓的mysql为什么要强调最左前缀原则的原因。  那么什么时候才能用到呢? 当然是cid字段的索引数据也是有序的情况下才能使用咯,什么时候才是有序的呢?观察可知,当然是在name字段是等值匹配的情况下,cid才是有序的。发现没有,观察两个name名字为 c 的cid字段是不是有序的呢。从上往下分别是4 5。 这也就是mysql索引规则中要求复合索引要想使用第二个索引,必须先使用第一个索引的原因。(而且第一个索引必须是等值匹配)。  所以对于执行3这条sql查询:  EXPLAIN SELECT * FROM student WHERE   cid=1 AND name='小红'; 1 没有错,而且复合索引中的两个索引字段都能很好的利用到了!因为语句中最左面的name字段进行了等值匹配,所以cid是有序的,也可以利用到索引了。  你可能会问:我建的索引是(name,cid)。而我查询的语句是cid=1 AND name=‘小红’; 我是先查询cid,再查询name的,不是先从最左面查的呀?  好吧,我再解释一下这个问题:首先可以肯定的是把条件判断反过来变成这样 name=‘小红’ and cid=1; 最后所查询的结果是一样的。 那么问题产生了?既然结果是一样的,到底以何种顺序的查询方式最好呢?  所以,而此时那就是我们的mysql查询优化器该登场了,mysql查询优化器会判断纠正这条sql语句该以什么样的顺序执行效率最高,最后才生成真正的执行计划。所以,当然是我们能尽量的利用到索引时的查询顺序效率最高咯,所以mysql查询优化器会最终以这种顺序进行查询执行。  相信通过以上的场景模拟,大家应该都或多或少更加理解了什么是最左前缀匹配原则,中间的弯弯绕绕实在会让我们迷惑很久,比如我。。(好吧,写完以后回头再看又感觉虽然把我想说的都写出来了,但是却不够通俗易懂,感觉表达能力稍微欠缺) 原文链接:https://blog.csdn.net/yuanchangliang/article/details/107798724 
  • [其他] 索引的结构介绍
    索引(Index)是数据库中用于快速查找和检索数据的数据结构。它允许数据库管理系统(DBMS)在不扫描整个表的情况下快速定位到特定的行或记录。索引的结构对于查询性能至关重要,不同类型的索引适用于不同的场景和需求。以下是一些常见的索引结构:B-Tree 索引:B-Tree(平衡多路搜索树)是一种自平衡的树数据结构,广泛用于数据库索引。它能够保持数据的有序性,并且每个节点都可以存储多个值,这使得B-Tree特别适合于处理大量数据。B-Tree 索引通常用于全范围扫描,如 BETWEEN 操作和排序。B+Tree 索引:B+Tree 是 B-Tree 的变体,区别在于 B+Tree 的所有实际数据都存储在叶子节点中,而非叶子节点仅存储键值信息。非叶子节点充当了索引的角色,叶子节点通过指针连接成一个有序链表,便于范围查询。B+Tree 索引通常用于频繁的读取操作,因为它能够提供更好的读取性能。Hash 索引:Hash 索引基于哈希表实现,它使用一个哈希函数将数据列的值转换为一个数字,然后根据这个数字快速定位到数据行。Hash 索引适合等值查询,如 = 和 <=> 操作符。Hash 索引不支持范围查询,因为哈希值之间没有顺序关系。位图 索引(Bitmap Index):位图索引主要用于低基数(即唯一值较少)的列,例如性别、状态等。每个唯一值都有一个位图,位图中的每个位对应一行数据,如果该行数据的列值与位图对应的唯一值相同,则该位为1,否则为0。位图索引可以极大地减少存储空间,并提高特定类型查询的速度。全文索引(Full-Text Index):全文索引用于支持全文搜索,允许用户对文本内容进行复杂的搜索操作,如关键词搜索、同义词处理等。它通常用于大型文本数据的搜索优化,如文章、评论等。GIN 索引(Generalized Inverted Index):GIN 索引是一种通用的倒排索引,适用于包含多种数据类型的列,如数组、全文等。它允许对复杂数据类型进行高效的查询操作。GIST 索引(Generalized Search Tree):GIST 索引是一种通用的搜索树索引,适用于地理空间数据和全文搜索等特殊类型的数据。它支持多种几何对象和全文搜索的查询操作。选择正确的索引类型取决于表的大小、数据的特性以及查询的类型。在实际应用中,可能需要根据具体情况调整或组合使用不同的索引结构,以达到最佳的查询性能。
  • [其他] sql查询中一个条件匹配用in和=的区别
     在SQL查询中,使用"="和"IN"进行ID匹配时,如果只匹配一个ID值,则两者通常没有性能上的差异。具体分析如下:  1. **单一值匹配**:当只需要匹配一个特定的ID时,使用"="和"IN"在功能上是等价的。例如,`SELECT * FROM table WHERE id = 1;` 等同于 `SELECT * FROM table WHERE id IN (1);`。在这种情况下,两者的效率相差无几,因为都只需比较一次。 2. **多值匹配**:当需要匹配多个ID时,应使用"IN"。"IN"的作用等同于多个"OR"连接的"="条件。例如,`SELECT * FROM table WHERE id IN (1, 2, 3);` 等同于 `SELECT * FROM table WHERE id = 1 OR id = 2 OR id = 3;`。此时,使用"IN"会更加方便和可读性更高。 3. **索引扫描**:"="操作符在进行索引扫描时通常效率较高,因为它只针对单个值进行查找。而"IN"虽然也是进行索引扫描且效率相对较高,但如果包含多个值,其内部可能需要进行多次比较。因此,对于单一数值的查询,"="可能会更快一些。 4. **查询优化**:如果在使用"IN"时包含了大量ID值,可能会导致查询性能下降。在这种情况下,可以考虑使用JOIN操作来代替"IN",通过将需要过滤的ID连接到表上,然后进行查询,这样有时可以提高查询效率。  综上所述,当查询条件中的ID只有一个时,使用"="和"IN"在效率和结果上没有区别。如果需要匹配多个ID值,则应当使用"IN"。在实际使用时,应根据具体情况选择合适的操作符,并考虑索引、查询优化等因素来提高查询性能。 
  • [技术干货] openGauss数据库常用sql指令
    openGauss数据库作为一款基于SQL标准的关系型数据库管理系统,支持广泛的SQL指令进行数据操作、查询、管理以及权限控制。以下是openGauss数据库中一些常用的SQL指令示例,涵盖了数据定义(DDL)、数据操纵(DML)、数据查询(DQL)和数据控制(DCL)等方面:数据定义(DDL)创建数据库CREATE DATABASE db_name;创建用户CREATE USER username WITH PASSWORD 'password';创建表CREATE TABLE table_name ( column1 datatype, column2 datatype, ... constraint_name constraint_type (column_list) ); -- 示例 CREATE TABLE employees ( id INT PRIMARY KEY, name VARCHAR(50) NOT NULL, department VARCHAR(50), salary DECIMAL(10, 2) );修改表结构ALTER TABLE table_name ADD COLUMN new_column datatype; -- 或 ALTER TABLE table_name DROP COLUMN column_to_remove;创建索引CREATE INDEX idx_name ON table_name (column_to_index);数据操纵(DML)插入数据INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...); -- 示例 INSERT INTO employees (id, name, department, salary) VALUES (1, 'John Doe', 'Sales', 50000.00);更新数据UPDATE table_name SET column1 = new_value1, column2 = new_value2, ... WHERE condition; -- 示例 UPDATE employees SET salary = salary * 1.1 WHERE department = 'Sales';删除数据DELETE FROM table_name WHERE condition; -- 示例 DELETE FROM employees WHERE department = 'Marketing';数据查询(DQL)基本查询SELECT column1, column2, ... FROM table_name WHERE condition ORDER BY column1 [ASC|DESC] LIMIT limit_count OFFSET offset_count; -- 示例 SELECT id, name, salary FROM employees WHERE department = 'IT' ORDER BY salary DESC LIMIT 10;聚合函数SELECT COUNT(*), AVG(salary), MAX(salary), MIN(salary) FROM employees;连接查询SELECT e.id, e.name, d.department_name FROM employees e JOIN departments d ON e.department = d.department_id;数据控制(DCL)授予权限GRANT privilege_list ON object TO user; -- 示例 GRANT SELECT, INSERT, UPDATE ON employees TO user1;撤销权限REVOKE privilege_list ON object FROM user;提交与回滚事务BEGIN TRANSACTION; -- 执行一系列操作... COMMIT; -- 提交事务,永久保存更改 -- 或 ROLLBACK; -- 回滚事务,取消所有未提交的更改会话管理ALTER SESSION SET parameter_name = value; -- 示例 ALTER SESSION SET search_path = 'public, my_schema';系统管理-- 查看数据库状态 SELECT pg_stat_activity FROM pg_catalog.pg_stat_activity; -- 重启数据库 SELECT pg_ctl restart;
  • [其他] SQL中等值匹配和in匹配哪个效率高
    在SQL中,等值匹配(如使用=操作符)和IN匹配(如使用IN()子句)的效率取决于具体的数据量和查询场景。以下是对两者在不同情况下效率的比较:数据量较小:当IN子句中包含的数据量较少时,IN匹配通常会更快,因为它可以快速确定需要匹配的值,并进行查询。数据量较大:如果IN子句中包含的数据量很大,那么等值匹配可能会更高效。因为在IN匹配中,数据库会对外表的每一行与内表的结果集进行匹配,这可能导致大量的重复比较,从而降低效率。索引使用:等值匹配通常可以利用索引优势,尤其是在主键关联或外键关联的情况下。如果等值匹配涉及的字段上有索引,那么查询效率会更高。查询优化器:数据库的查询优化器会根据查询的具体情况选择最优的执行计划。在某些情况下,即使使用了IN子句,查询优化器也可能会选择先执行外部查询,再根据结果执行内部查询。综上所述,等值匹配和IN匹配各有优势,没有绝对的效率高低之分。在实际应用中,应根据具体的数据量、索引情况和查询需求来选择合适的匹配方式。在数据量较小或需要精确匹配特定值时,IN匹配可能更合适;而在数据量大且有索引支持的情况下,等值匹配可能更有效率。如果只有一个值的匹配呢?在大多数情况下,对于单个值的匹配,等值匹配(使用=操作符)通常会比IN匹配(使用IN()子句)更高效。具体原因如下:索引利用:等值匹配更容易利用到数据库的索引优势。如果查询的字段上有索引,等值匹配可以快速定位到具体的数据行,而不需要像IN匹配那样对结果集进行多次比较。查询计划:数据库的查询优化器在处理等值匹配时,往往能够生成更高效的查询执行计划。这是因为等值匹配通常涉及到的是简单的点查询,而IN匹配可能需要进行更复杂的集合运算。避免重复比较:在IN匹配中,尤其是当内表(即IN子句中的值的集合)较大时,可能会导致大量的重复比较,从而降低查询效率。而等值匹配则避免了这种重复比较的情况。综上所述,如果是针对单个值的匹配,等值匹配通常提供更好的性能。但是,具体情况还需要根据实际的数据、索引情况以及数据库的具体实现来确定。在某些特定的情况下,数据库优化器可能会采取一些策略,使得IN匹配的性能与等值匹配相当。因此,建议在实际操作中,根据具体的查询需求和环境进行测试,以确定最佳的查询方法。
  • [技术干货] SQL使用大全-转载
     SQL使用大全 SQL简介 SQL,全称为Structured Query Language,即结构化查询语言,是一种用于管理关系数据库的标准语言。SQL语言包括数据定义语言(DDL),数据操作语言(DML),数据控制语言(DCL)等。本文将详细介绍SQL的常见操作,包括创建表、查询、修改、删除等操作。  CREATE TABLE CREATE TABLE用法简介 CREATE TABLE是SQL的数据定义语言(DDL)中的一部分,用于创建新的数据库表。其基本语法如下:  CREATE TABLE table_name (     column1 datatype,     column2 datatype,     column3 datatype,    .... ); 使用CREATE TABLE创建用户表 例如,我们可以使用CREATE TABLE创建一个名为Users的表,包含id、name和email三个字段:  CREATE TABLE Users (     id INT,     name VARCHAR(100),     email VARCHAR(100) ); 1 2 3 4 5 SELECT 和 FROM SELECT 和 FROM用法简介 SELECT 和 FROM是SQL的数据操作语言(DML)中的一部分,用于从数据库表中查询数据。SELECT用于指定要查询的列,FROM用于指定要查询的表。其基本语法如下:  SELECT column1, column2, ... FROM table_name; 1 2 使用SELECT 和 FROM查询用户表 例如,我们可以使用SELECT 和 FROM从Users表中查询所有用户的id和name:  SELECT id, name FROM Users; 1 2 ALTER TABLE ALTER TABLE用法简介 ALTER TABLE是SQL的数据定义语言(DDL)中的一部分,用于修改数据库表的结构。其基本语法如下:  ALTER TABLE table_name ADD column_name datatype; 1 2 使用ALTER TABLE修改用户表的字段名 例如,我们可以使用ALTER TABLE将Users表的name字段改名为username:  ALTER TABLE Users RENAME COLUMN name TO username; 1 2 使用ALTER TABLE修改用户表的字段类型 例如,我们可以使用ALTER TABLE将Users表的id字段的类型改为VARCHAR:  ALTER TABLE Users ALTER COLUMN id TYPE VARCHAR; 1 2 使用ALTER TABLE修改用户表的字段注释 例如,我们可以使用ALTER TABLE为Users表的email字段添加注释:  ALTER TABLE Users COMMENT ON COLUMN email IS '用户的电子邮件地址'; 1 2 WHERE WHERE用法简介 WHERE是SQL的数据操作语言(DML)中的一部分,用于在查询时设置条件。其基本语法如下:  SELECT column1, column2, ... FROM table_name WHERE condition; 1 2 3 使用WHERE的AND查询用户表 例如,我们可以使用WHERE的AND从Users表中查询id为1且name为’John’的用户:  SELECT * FROM Users WHERE id = 1 AND name = 'John'; 1 2 3 使用WHERE的OR查询用户表 例如,我们可以使用WHERE的OR从Users表中查询id为1或name为’John’的用户:  SELECT * FROM Users WHERE id = 1 OR name = 'John'; 1 2 3 使用WHERE的IN查询用户表 例如,我们可以使用WHERE的IN从Users表中查询id为1、2、3的用户:  SELECT * FROM Users WHERE id IN (1, 2, 3); 1 2 3 使用WHERE的BETWEEN查询用户表 例如,我们可以使用WHERE的BETWEEN从Users表中查询id在1到3之间的用户:  SELECT * FROM Users WHERE id BETWEEN 1 AND 3; 使用WHERE的LIKE查询用户表 例如,我们可以使用WHERE的LIKE从Users表中查询name以’J’开头的用户:  SELECT * FROM Users WHERE name LIKE 'J%'; UPDATE UPDATE用法简介 UPDATE是SQL的数据操作语言(DML)中的一部分,用于修改数据库表中的数据。其基本语法如下:  UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition; 1 2 3 使用UPDATE修改用户表的记录 例如,我们可以使用UPDATE将Users表中id为1的用户的name修改为’Jack’:  UPDATE Users SET name = 'Jack' WHERE id = 1; DELETE DELETE用法简介 DELETE是SQL的数据操作语言(DML)中的一部分,用于删除数据库表中的数据。其基本语法如下:  DELETE FROM table_name WHERE condition; 1 使用DELETE删除用户表的记录 例如,我们可以使用DELETE删除Users表中id为1的用户:  DELETE FROM Users WHERE id = 1; ORDER BY ORDER BY用法简介 ORDER BY是SQL的数据操作语言(DML)中的一部分,用于对查询结果进行排序。其基本语法如下:  SELECT column1, column2, ... FROM table_name ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...; 使用ORDER BY查询用户表 例如,我们可以使用ORDER BY从Users表中查询所有用户,并按照id降序排序:  SELECT * FROM Users ORDER BY id DESC; GROUP BY GROUP BY用法简介 GROUP BY是SQL的数据操作语言(DML)中的一部分,用于对查询结果进行分组。其基本语法如下:  SELECT column1, column2, ... FROM table_name GROUP BY column1, column2, ...; 使用GROUP BY查询用户表 例如,我们可以使用GROUP BY从Users表中查询每个name的用户数量:  SELECT name, COUNT(*) FROM Users GROUP BY name; HAVING HAVING用法简介 HAVING是SQL的数据操作语言(DML)中的一部分,用于对GROUP BY的结果进行过滤。其基本语法如下:  SELECT column1, column2, ... FROM table_name GROUP BY column1, column2, ... HAVING condition; 使用HAVING查询用户表 例如,我们可以使用HAVING从Users表中查询用户数量大于1的name:  SELECT name, COUNT(*) FROM Users GROUP BY name 总结 以上就是SQL的常见操作的详细介绍,包括创建表、查询、修改、删除等操作。希望对你有所帮助,如果你有任何问题,欢迎留言讨论。 ————————————————                              版权声明:本文为博主原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接和本声明。                          原文链接:https://blog.csdn.net/heihaozi/article/details/134373617 
  • GaussDB(DWS) SQL执行报错:query cpu time on datanodes limit exceeds
    【版本信息】813【问题现象】SQL执行时报错:query cpu time on datanodes limit exceeds【 原因分析】1. 此报错为资源池异常规则,受allcputime和cpuskewpercent管控,超阈值后abort;当实际值超过异常规则设置值时会触发query cpu time on datanodes limit exceeds告警。其中:allcputime表示作业在所有DN上执行时所耗费的CPU总时间,单位秒。cpuskewpercent表示作业在DN上执行时的CPU时间的倾斜率,依赖于qualificationtime的设置。qualificationtime表示检查作业执行cpu倾斜率的间隔时间,单位秒,需同cpuskewpercent一起设置。abort表示作业满足设置的异常阈值后执行终止作业,可以通过参数“-a”或“--abort”指定。2. 实例中查看资源池异常规则发现allcputime=0,cpuskewpercent=95;(查看方式详见下节)【处理方法】连接数据库后,首先查看某个资源池关联的查询规则信息:SELECT * FROM gs_respool_exception_info('default_pool');     2. 重写该SQL语句,采用Gaussdb的计算倾斜优化机制:cid:link_0如果仍未解决或重写SQL不可行,则建议用户升级至820版本。
  • [问题求助] 使用数据库接口方式,obs获取外呼任务失败
    问题来源】【必填】    【南海农商行】    【问题简要】【必填】 ICD V300R008C25 数据库接口方式 obs 获取外呼任务失败【问题类别】【必填】    【可选问题分类:ICD obs】【AICC解决方案版本】【必填】    【AICC可选择版本:AICC 22.100】    【UAP可选择版本:V100R005】    【CTI可选择版本:ICD V300R008C25SPC012】【期望解决时间】【选填】尽快【问题现象描述】【必填】一个新配置的VDN,已成功获调用【取外呼管理系统接口协议版本号】和【取接口名称接口】当要调用【取外呼任务接口】时,发现报错2023-12-12 17:27:25 [9542] [RUN] [INFO] [21035] 提示信息: Func:ReadTask proc was executed once 2023-12-12 17:27:25 [9542] [RUN] [ERROR] [21042] ProxyApi获取结果集信息错误 Func:ReadTask,DBName:vdnWork3,VdnId:2 Return:2706 2023-12-12 17:27:25 [9542] [RUN] [ERROR] [21009] 获取外呼任务失败 Subccno:1,VdnID=2,DbS=vdnWork3,UserName:,Error Code :34678 2023-12-12 17:27:25 [9542] [RUN] [INFO] [21035] 提示信息: Func:ReadTask proc was executed once 2023-12-12 17:27:25 [9542] [RUN] [ERROR] [21042] ProxyApi获取结果集信息错误 Func:ReadTask,DBName:vdnWork3,VdnId:2 Return:2706 2023-12-12 17:27:25 [9542] [RUN] [ERROR] [21009] 获取外呼任务失败 Subccno:1,VdnID=2,DbS=vdnWork3,UserName:,Error Code :34678 2023-12-12 17:27:36 [9542] [RUN] [INFO] [21035] 提示信息: Func:ReadTask proc was executed once 2023-12-12 17:27:36 [9542] [RUN] [INFO] [21035] 提示信息: Func:ReadTask proc was executed once 2023-12-12 17:27:36 [9542] [RUN] [ERROR] [21042] ProxyApi获取结果集信息错误 Func:ReadTask,DBName:vdnWork3,VdnId:2 Return:2706 2023-12-12 17:27:36 [9542] [RUN] [ERROR] [21009] 获取外呼任务失败 Subccno:1,VdnID=2,DbS=vdnWork3,UserName:,Error Code :34678在接口文档上要求,【取外呼任务接口】要求返回结果集。使用MySQL,初次接触存储过程,我不知道返回结果集。暂时通过sql的select语句查询需要的数据,然后参数返回的结果集那个参数out o_TaskData只是赋值为0.自己调用存储过程,效果如下:我自己以为这样子可以获取到接口需要的参数。当select @o_TaskData时:所有,我想请教一下,是不是我这个存储过程返回的结果集这个参数的内容不对引起上面的报错?
  • [其他] sql查询中的查询规范
     在SQL查询中,查询规范是非常重要的一部分,它可以帮助数据库管理系统正确地执行查询并提高查询效率。以下是一些常见的查询规范示例:  1. 使用小写字母和下划线命名表和列名,避免使用大写字母和空格。例如,将表名命名为"employees",将列名命名为"first_name"、"last_name"等。  2. 使用主键约束来唯一标识表中的每一行数据。主键通常是一个或多个字段的组合,用于确保数据的完整性和一致性。  3. 使用外键约束来建立表之间的关系。外键是一个或多个字段的组合,用于引用另一个表中的主键。这有助于维护数据的一致性和完整性。  4. 使用索引来加速查询操作。索引可以大大提高查询速度,特别是在大型数据库中。但是,索引也会占用额外的存储空间,并且可能会降低插入和更新操作的速度。因此,在使用索引时需要权衡利弊。  5. 避免使用SELECT *语句,而是明确指定要查询的列。这样可以减少数据传输量,提高查询效率。  6. 使用LIMIT子句来限制查询结果的数量。这可以帮助减少处理时间和内存消耗。  7. 使用JOIN子句来连接多个表。这可以帮助从多个表中获取数据并进行复杂的查询操作。  8. 使用GROUP BY子句来对结果进行分组。这可以帮助对数据进行聚合操作,如计算总和、平均值等。  9. 使用HAVING子句来过滤分组后的结果。这可以帮助进一步筛选数据,只返回满足特定条件的组。  10. 使用ORDER BY子句来对结果进行排序。这可以帮助用户更好地理解查询结果的顺序。  总之,遵循这些查询规范可以提高SQL查询的效率和可读性。 
  • [其他] sql查询中字符串相等匹配和数字相等匹配哪个效率高?
     在SQL查询中,字符串相等匹配和数字相等匹配的效率可能会受到多种因素的影响。一般来说,字符类型有字符集的概念,每次从存储端到展现端之间都有一个字符集编码的过程。这一过程主要消耗的是CPU资源,对于In-memory的操作来说,这是一个不可忽视的消耗。而数字类型的比较则相对简单,因此在某些情况下,数字相等匹配可能效率更高。  然而,这并不是绝对的。实际的效率差异还可能取决于数据库的类型、版本、配置以及具体的数据和查询条件。例如,某些数据库可能在处理字符串匹配时进行了优化,或者在处理大量数字数据时存在特定的硬件加速机制。  此外,还需要注意的是,SQL提供了不同的匹配模式,如LIKE运算符和=运算符。这些运算符在处理字符串匹配时的行为可能会有所不同,例如,LIKE运算符支持部分字符串匹配,而=运算符则假定两个字符串完全相同。因此,在选择查询方式时,除了考虑匹配类型(字符串或数字)外,还需要根据具体的查询需求选择合适的匹配模式。 
  • [技术干货] SQL Server两表数据同步的多种方法详解【转】
    一、引言A表数据同步至B表的场景很常见,比如一个公司有总部及分厂,它们使用相同的系统,只是账套不同。此时,一些基础数据如物料信息,只需要总部录入即可,然后间隔一定时间同步至分厂,避免了重复工作。二、测试数据CREATE TABLE StudentA (     ID VARCHAR(32),     Name VARCHAR(20),     Sex VARCHAR(10) ) GO INSERT INTO StudentA (ID,Name,Sex) SELECT '1001','张三','男' UNION SELECT '1002','李四','男' UNION SELECT '1003','王五','女' GO CREATE TABLE StudentB (     ID VARCHAR(32),     Name VARCHAR(20),     Sex VARCHAR(10) ) GO INSERT INTO StudentB (ID,Name,Sex) SELECT '1001','张三','女' UNION SELECT '1002','李四','女' UNION SELECT '1003','王五','女' UNION SELECT '1004','赵六','女'三、数据同步方法3.1、TRUNCATE TABLETRUNCATE TABLE dbo.StudentB INSERT INTO dbo.StudentB SELECT * FROM dbo.StudentA3.2、CHECKSUMDELETE FROM dbo.StudentB WHERE NOT EXISTS (SELECT 1 FROM dbo.StudentA WHERE ID=dbo.StudentB.ID) UPDATE B SET B.Name=A.Name,B.Sex=A.Sex FROM dbo.StudentA A INNER JOIN dbo.StudentB B ON A.ID=B.ID WHERE CHECKSUM(A.Name,A.Sex)<>CHECKSUM(B.Name,B.Sex) INSERT INTO dbo.StudentB SELECT * FROM dbo.StudentA WHERE NOT EXISTS (SELECT 1 FROM dbo.StudentB WHERE ID=dbo.StudentA.ID)3.3、MERGE INTOMERGE INTO dbo.StudentB AS T USING dbo.StudentA AS S ON T.ID=S.ID WHEN MATCHED THEN                --当ON条件成立时,更新数据。     UPDATE SET T.Name=S.Name,T.Sex=S.Sex WHEN NOT MATCHED THEN            --当源表数据不存在于目标表时,插入数据。     INSERT VALUES (S.ID,S.Name,S.Sex) WHEN NOT MATCHED BY SOURCE THEN  --当目标表数据不存在于源表时,删除数据。     DELETE;
  • [技术干货] SqlServer数据库脚本执行命令行指令方式【转】
    SqlServer脚本执行命令行指令1.用户登录,首先打开命令提示符窗口,假设:用户是testor,密码是123,输入如下12C:\Windows\System32>osql -S 127.0.0.1 -U testor -P 1231>2.查看数据库,可以输入如下:121> select name from sysdatabases2> go3.创建数据库,输入如下121> create database testdb12> go4.执行sql文件,先查找sqlserver的工具目录,我的是C:\Program Files\Microsoft SQL Server\150\Tools\Binn,在该目录地址栏输入cmd,再执行以下脚本,其中-d selecteddb 本来是选择数据库,不过我这个数据库版本貌似没有起效1sqlcmd -S . -U 用户名 -P 密码 -d selecteddb -i E:\somesql.sql好了,sqlserver的分享就这样了,反正觉着没有mysql或者mariadb好用,凑合用吧SqlServer命令行的使用1.连接sqlserver1sqlcmd -S localhost\sqlserver_name2.连接数据库1sqlcmd -S localhost\sqlserver_name -d database_name3.执行SQL语句1sqlcmd -S localhost\sqlserver_name -d database_name -Q "SELECT * FROM [table_name]"4.执行SQL脚本文件1sqlcmd -S localhost\sqlserver_name -d database_name -i "SQL file path"5.将查询的结果集输出到文件1sqlcmd -S localhost\sqlserver_name -d database_name -o "file path"6.输出的结果集字符较长,输出到控制台和文本都不能显示完全,需要再加一个参数12sqlcmd -S localhost\sqlserver_name -d database_name -y 1024 -Q "SELECT * FROM [table_name]"-- 注:此处的“-y”后面的值可以更改,如果还是不能完全显示,将数值再改大一点7.查询sqlserver 命令参数1sqlcmd -?8.备份数据库123> sqlcmd -S localhost\sqlserver_name> backup database database_name to disk='E:\backup\database_name.bak'> go9.通过database_name.bak文件查询逻辑名1restore filelistonly from disk='path/to/backup/file.bak'10.恢复数据库12345678910111213--(1)先查询数据库是否存在,存在就删除-- a. 查询数据库> sqlcmd -S localhost\sqlserver_name> select [Name] from [sysdatabases]> go-- b. 删除数据库> drop database database_name(2)恢复数据库,在进入实例服务的情况下(即sqlcmd -S localhost\sqlserver_name)执行以下语句:> restore database database_name from disk='D:\backup\database_name.bak'> with> move 'database_name' to 'D:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\database_name.mdf',> move 'database_name_log' to 'D:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\database_name_log.ldf'> go11. 修改数据库的名称12345> restore database update_database_name from disk='E:\backup\database_name.bak'> with> move 'database_name' to 'E:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\update_database_name.mdf',> move 'database_name_log' to 'E:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\update_database_name_log.ldf'> go12. 获取数据的逻辑名和日志逻辑名1234-- 方式一:select file_name(1),file_name(2)-- 方式二:SELECT name FROM sys.database_files 13. 修改数据的逻辑名或者日志逻辑名12ALTER DATABASE [database_name] MODIFY FILE ( NAME = database_name, NEWNAME = new_database_name ) ALTER DATABASE [database_name] MODIFY FILE ( NAME = database_nameb_log, NEWNAME = new_database_name_log ) 14. 查询数据文件或日志文件当前存放路径1SELECT physical_name FROM sys.database_files 15. bcp 命令的使用12345678-- 导出整张表bcp MDataPort.dbo.Recording out E:\Backup\recording.bcp -S .\sqlexpress -T -c-- 导入整张表bcp MDataPort.dbo.Recording in E:\Backup\recording.bcp -S .\sqlexpress -T -c-- 导出指定时间戳bcp "select * from MDataPort.dbo.Recording where Timestamp >= '2019-02-01 00:00:00'" queryout E:\Backup\recording_20190201.bcp -S .\sqlexpress -T -c-- 导出指定列bcp "select Timestamp from MDataPort.dbo.Recording" queryout E:\Backup\recording_Timestamp.bcp -S .\sqlexpress -T -c16.   row_number()分页12345678-- 对源表进行重新排序,并增加一个排序的ID字段 select row_number() over(order by id) as ROWID, *  from [table_name])  as new_table_namewhere ROWID > OnePageNum* (CurrentPage-1)--原理:先把表中的所有数据都按照一个rowNumber进行排序,然后查询rownuber大于40的前十条记录-- 这种方法和oracle中的一种分页方式类似,不过只支持2005版本以上的-- Annotation:OnePageNum每页显示的记录数    -- CurrentPage:当前页页数 注1:以上连接数据库的方式都是windows自动验证连接注2:若是恢复失败的话,可以找到sqlserver安装目录(即MSSQL11.SQLEXPRESS)右击属性---->安全---->查看User权限的权限注3:sqlserver_name:数据库服务名        database_name:数据库名         table_name:表名
  • [技术干货] 使用SQL语句创建触发器的实例【转】
    前言一、触发器的介绍1.1 触发器 的概念以及定义:触发器 是一种特殊类型的存储过程,它不同于我们前面介绍过的存储过程。存储过程可以通过语句直接调用,而 触发器主要是通过事件进行触发而被执行的.例如当对某一表进行诸如UPDATE(修改)、INSERT(插入)、DELETE(删除)这些操作时,SQL Server 就会自动执行触发器所定义的SQL语句,从而确保对数据之间的相互关系,实时更新.1.2 、 触发器 的作用触发器的主要作用就是其能够实现由 主键 和 外键 所不能保证的复杂的参照完整性和数据的一致性。除此之外, 触发器 还有其它许多不同的功能:①、复杂的约束条件触发器 能够实现比CHECK 语句更为复杂的约束。②、保证数据的安全触发器 因为 触发器是在对数据库进行相应的操作而自动被触发的SQL语句可以通过数据库内的操作从而不允许数据库中未经许可的指定更新和变化。③.级联式触发器 可以根据数据库内的操作,并自动地级联影响整个数据库的各项内容。例如:对A表进行操作时,导致A表上的 触发器被触发,A中的 触发器中包含有对B表的数据操作(UPDATE(修改)、INSERT(插入)、DELETE(删除)),而该操作又导致B表上 触发器被触发。④.调用存储过程为了响应数据库更新, 触发器 可以调用一个或多个存储过程.但是,总体而言, 触发器性能通常比较低。二、 触发器 的种类SQL Server 中一般支持以下两种类型的触发器:AFTER 触发器  AFTER 触发器 要求只有执行某一操作(INSERT、UPDATE、DELETE)之后, 触发器 才被触发,且只能在表上定义。可以为针对表的同一操作定义多个 触发器 。2. INSTEAD OF 触发器 。  INSTEAD OF 触发器 表示并不执行其所定义的操作(INSERT、UPDATE、DELETE),而仅是执行 触发器 本身。既可在表上定义INSTEAD OF 触发器 ,也可以在视图上定义INSTEAD OF 触发器 ,但对同一操作只能定义一个INSTEAD OF 触发器 。三、使用SQL语句创建触发器实例1.创建after融发器(1)创建一个在插入时触发的触发器sc_insert,当向sc表插入数据时,须确保插入的学号已在student表中存在,并且还须确保插入的课程号在Course表中存在﹔若不存在,则给出相应的提示信息,并取消插入操作,提示信息要求指明插入信息是学号不满足条件还是课程号不满足条件(注:Student表与sc表的外键约束要先取消)。语句实现:.create trigger sc_insert on sc after insert as if not exists (select * from student,inserted             where student.sno=inserted.sno)     begin         print '插入信息的学号不在学生表中! '         if not exists (select * from course,inserted where         course.cno=inserted. cno)         print '插入信息的课程号不在课程表中!'         rollback     end   else         begin             if not exists (select * from course,inserted where         Course.cno=inserted.cno)             begin             print '插入信息的课程号不在课程表中! '             rollback         end     end为Course表创建一个触发器Course_del,当删除了Course表中的一条课程信息时,同时将表sc表中相应的学生选课记录删除掉。create trigger course_del on course after delete as if exists(select * from sc, deleted where sc.cno=deleted.cno) begin delete from sc where sc.cno in (select cno from deleted) end delete from Course where Cno='003'创建Grade_modify触发器create trigger Grade_modify on sc after update as if update(grade) begin update course set avg_grade=(select avg (grade) from sc where course.cno=sc.cno group by cno) end update sc set Grade='90 ' where sno='20050001' and cno='001'2.创建instead of触发器(1)创建一视图Student_view,包含学号、姓名、课程号、课程名、成绩等属性,在Student_view上创建一个触发器Grade_moidfy,当对Student_view中的学生的成绩进行修改时,实际修改的是sc中的相应记录。创建视图:12345create view student_viewasselect s.Sno,Sname , c.Cno , Cname , Gradefrom student s , course c, scwhere s.Sno=sc.sno and c.Cno=sc.cno创建触发器:12345678910111213create trigger Grade_moidfy on student_viewinstead of updateasif UPDATE (Grade)beginupdate scset Grade= (select Grade from inserted) whereSno= (select sno from inserted) andCno= (select Cno from inserted)Endupdate student_viewset Grade=40where Sno='20110001'and Cno='002'测试修改数据:12select *from student_view(2)在sc表中插入一个getcredit字段(记录某学生,所选课程所获学分的情况),创建一个触发器ins_credit,当更改(注:含插入时)sc表中的学生成绩时,如果新成绩大于等于60分,则该生可获得这门课的学分,且该学分须与Course表中的值一致﹔如果新成绩小于60分,则该生未能获得学分,修改值为0。添加新字段getcredit :12alter table scadd getcredit smallint创建触发器:123456789101112131415create trigger sc_upon scafter insert,updateasdeclare @xf int,@kch char(3),@xh char(8),@fs intselect @fs=grade,@kch=cno,@xh=sno from insertedif @fs>=60update sc set @xf=(select credit from course wheresc.Cno=course.cno) where sno=@xh and cno=@kchelseupdate sc set @xf=0 where sno=@xh and cno=@kch修改数据:update scset Grade='90'where Sno='20050001' and cno='001'
  • [技术干货] SQL中EXISTS的用法示例详解【转】
    SQL中EXISTS的用法比如在Northwind数据库中有一个查询为SELECT c.CustomerId,CompanyName FROM Customers cWHERE EXISTS(SELECT OrderID FROM Orders o WHERE o.CustomerID=c.CustomerID) 这里面的EXISTS是如何运作呢?子查询返回的是OrderId字段,可是外面的查询要找的是CustomerID和CompanyName字段,这两个字段肯定不在OrderID里面啊,这是如何匹配的呢? EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或FalseEXISTS 指定一个子查询,检测 行 的存在。语法: EXISTS subquery参数: subquery 是一个受限的 SELECT 语句 (不允许有 COMPUTE 子句和 INTO 关键字)。结果类型: Boolean 如果子查询包含行,则返回 TRUE ,否则返回 FLASE 。(一). 在子查询中使用 NULL 仍然返回结果集select * from TableIn where exists(select null)等同于: select * from TableIn (二). 比较使用 EXISTS 和 IN 的查询。注意两个查询返回相同的结果。select * from TableIn where exists(select BID from TableEx where BNAME=TableIn.ANAME)select * from TableIn where ANAME in(select BNAME from TableEx)(三). 比较使用 EXISTS 和 = ANY 的查询。注意两个查询返回相同的结果。select * from TableIn where exists(select BID from TableEx where BNAME=TableIn.ANAME)select * from TableIn where ANAME=ANY(select BNAME from TableEx)NOT EXISTS 的作用与 EXISTS 正好相反。如果子查询没有返回行,则满足了 NOT EXISTS 中的 WHERE 子句。结论:EXISTS(包括 NOT EXISTS )子句的返回值是一个BOOL值。 EXISTS内部有一个子查询语句(SELECT ... FROM...), 我将其称为EXIST的内查询语句。其内查询语句返回一个结果集。 EXISTS子句根据其内查询语句的结果集空或者非空,返回一个布尔值。一种通俗的可以理解为:将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果取非空值,则EXISTS子句返回TRUE,这一行行可作为外查询的结果行,否则不能作为结果。分析器会先看语句的第一个词,当它发现第一个词是SELECT关键字的时候,它会跳到FROM关键字,然后通过FROM关键字找到表名并把表装入内存。接着是找WHERE关键字,如果找不到则返回到SELECT找字段解析,如果找到WHERE,则分析其中的条件,完成后再回到SELECT分析字段。最后形成一张我们要的虚表。WHERE关键字后面的是条件表达式。条件表达式计算完成后,会有一个返回值,即非0或0,非0即为真(true),0即为假(false)。同理WHERE后面的条件也有一个返回值,真或假,来确定接下来执不执行SELECT。分析器先找到关键字SELECT,然后跳到FROM关键字将STUDENT表导入内存,并通过指针找到第一条记录,接着找到WHERE关键字计算它的条件表达式,如果为真那么把这条记录装到一个虚表当中,指针再指向下一条记录。如果为假那么指针直接指向下一条记录,而不进行其它操作。一直检索完整个表,并把检索出来的虚拟表返回给用户。EXISTS是条件表达式的一部分,它也有一个返回值(true或false)。在插入记录前,需要检查这条记录是否已经存在,只有当记录不存在时才执行插入操作,可以通过使用 EXISTS 条件句防止插入重复记录。INSERT INTO TableIn (ANAME,ASEX) SELECT top 1 '张三', '男' FROM TableInWHERE not exists (select * from TableIn where TableIn.AID = 7)EXISTS与IN的使用效率的问题,通常情况下采用exists要比in效率高,因为IN不走索引,但要看实际情况具体使用:IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。in、not in、exists和not exists的区别:先谈谈in和exists的区别:exists:存在,后面一般都是子查询,当子查询返回行数时,exists返回true。select * from class where exists (select'x"form stu where stu.cid=class.cid)当in和exists在查询效率上比较时,in查询的效率快于exists的查询效率exists(xxxxx)后面的子查询被称做相关子查询, 他是不返回列表的值的.只是返回一个ture或false的结果(这也是为什么子查询里是select 'x'的原因 当然也可以select任何东西) 也就是它只在乎括号里的数据能不能查找出来,是否存在这样的记录。其运行方式是先运行主查询一次 再去子查询里查询与其对应的结果 如果存在,返回ture则输出,反之返回false则不输出,再根据主查询中的每一行去子查询里去查询.执行顺序如下:1.首先执行一次外部查询2.对于外部查询中的每一行分别执行一次子查询,而且每次执行子查询时都会引用外部查询中当前行的值。3.使用子查询的结果来确定外部查询的结果集。如果外部查询返回100行,SQL   就将执行101次查询,一次执行外部查询,然后为外部查询返回的每一行执行一次子查询。in:包含查询和所有女生年龄相同的男生select * from stu where sex='男' and age in(select age from stu where sex='女')in()后面的子查询 是返回结果集的,换句话说执行次序和exists()不一样.子查询先产生结果集,然后主查询再去结果集里去找符合要求的字段列表去.符合要求的输出,反之则不输出.not in和not exists的区别:not in 只有当子查询中,select 关键字后的字段有not null约束或者有这种暗示时用not in,另外如果主查询中表大,子查询中的表小但是记录多,则应当使用not in,例如:查询那些班级中没有学生的,select * from class where cid not in(select distinct cid from stu)当表中cid存在null值,not in 不对空值进行处理解决:select * from classwhere cid not in(select distinct cid from stu where cid is not null)not in的执行顺序是:是在表中一条记录一条记录的查询(查询每条记录)符合要求的就返回结果集,不符合的就继续查询下一条记录,直到把表中的记录查询完。也就是说为了证明找不到,所以只能查询全部记录才能证明。并没有用到索引。not exists:如果主查询表中记录少,子查询表中记录多,并有索引。例如:查询那些班级中没有学生的,select * from class2where not exists(select * from stu1 where stu1.cid =class2.cid)not exists的执行顺序是:在表中查询,是根据索引查询的,如果存在就返回true,如果不存在就返回false,不会每条记录都去查询。之所以要多用not exists,而不用not in,也就是not exists查询的效率远远高与not in查询的效率。