当前位置:首页 » 编程语言 » 为什么在sql语句中应减少
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

为什么在sql语句中应减少

发布时间: 2022-06-30 05:15:16

1. 谁能告诉我怎样优化sql语句

(1)选择最有效率的表名顺序(只在基于规则的优化器中有效):Oracle的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表。(2)WHERE子句中的连接顺序:Oracle采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。(3)SELECT子句中避免使用‘*’:Oracle在解析的过程中, 会将‘*’依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间。(4)减少访问数据库的次数:Oracle在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等。(5)在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200。(6)使用DECODE函数来减少处理时间:使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表。(7)整合简单,无关联的数据库访问:如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)。(8)删除重复记录:最高效的删除重复记录方法 ( 因为使用了ROWID)例子:DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X WHERE X.EMP_NO = E.EMP_NO);
(9)用TRUNCATE替代DELETE:当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息。当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短。(TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)。(10)尽量多使用COMMIT:只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少,COMMIT所释放的资源:a. 回滚段上用于恢复数据的信息。b. 被程序语句获得的锁。c. redo log buffer 中的空间。d. Oracle为管理上述3种资源中的内部花费。(11)用Where子句替换HAVING子句:避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。(非oracle中)on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后,因为on是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的,where也应该比having快点的,因为它过滤数据后才进行sum,在两个表联接时才用on的,所以在一个表的时候,就剩下where跟having比较了。在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where可以使用rushmore技术,而having就不能,在速度上后者要慢如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作流程,where的作用时间是在计算之前就完成的,而having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。在多表联接查询时,on比where更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行过滤,然后再计算,计算完后再由having进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定放在那里。(12)减少对表的查询:在含有子查询的SQL语句中,要特别注意减少对表的查询。例子:SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT
TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
(13)通过内部函数提高SQL效率:复杂的SQL往往牺牲了执行效率。能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的。(14)使用表的别名(Alias):当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上。这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。(15)用EXISTS替代IN、用NOT EXISTS替代NOT IN:在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率。在子查询中,NOT IN子句将执行一个内部的排序和合并。无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历)。为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS。例子:(高效)SELECT * FROM EMP (基础表)
WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0
AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
(16)识别‘低效执行’的SQL语句:虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始终是一个最好的方法:SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,
SQL_TEXT
FROM V$SQLAREA
WHERE EXECUTIONS>0
AND BUFFER_GETS > 0
AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8
ORDER BY 4 DESC;
(17)用索引提高效率:索引是表的一个概念部分,用来提高检索数据的效率,Oracle使用了一个复杂的自平衡B-tree结构。通常,通过索引查询数据比全表扫描要快。当Oracle找出执行查询和Update语句的最佳路径时, Oracle优化器将使用索引。同样在联结多个表时使用索引也可以提高效率。另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证。那些LONG或LONG RAW数据类型, 你可以索引几乎所有的列。通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效率。虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价。索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改。这意味着每条记录的INSERT, DELETE , UPDATE将为此多付出4, 5次的磁盘I/O 。因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。定期的重构索引是有必要的:ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
(18)用EXISTS替换DISTINCT:当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT。一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果。例子:(低效):
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E
WHERE D.DEPT_NO = E.DEPT_NO
(高效):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X'
FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
(19)SQL语句用大写的;因为Oracle总是先解析SQL语句,把小写的字母转换成大写的再执行。(20)在Java代码中尽量少用连接符“+”连接字符串。(21)避免在索引列上使用NOT通常,我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响。当Oracle“遇到”NOT,他就会停止使用索引转而执行全表扫描。(22)避免在索引列上使用计算。WHERE子句中,如果索引列是函数的一部分。优化器将不使用索引而使用全表扫描。举例:低效:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;
(23)用>=替代>:高效:
SELECT * FROM EMP WHERE DEPTNO >=4
低效:
SELECT * FROM EMP WHERE DEPTNO >3
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录。(24)用UNION替换OR (适用于索引列):通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果。对索引列使用OR将造成全表扫描。注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低。在下面的例子中, LOC_ID 和REGION上都建有索引。高效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE REGION = “MELBOURNE”
低效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10 OR REGION = “MELBOURNE”
(25)用IN来替换OR:这是一条简单易记的规则,但是实际的执行效果还须检验,在Oracle8i下,两者的执行路径似乎是相同的:低效:SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30高效:SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30);(26)避免在索引列上使用IS NULL和IS NOT NULL:避免在索引中使用任何可以为空的列,Oracle将无法使用该索引。对于单列索引,如果列包含空值,索引中将不存在此记录。对于复合索引,如果每个列都为空,索引中同样不存在此记录.如果至少有一个列不为空,则记录存在于索引中。举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , Oracle将不接受下一条具有相同A,B值(123,null)的记录(插入)。 然而如果所有的索引列都为空,Oracle将认为整个键值为空而空不等于空。因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引。低效: (索引失效)SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;高效: (索引有效)SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;(27)总是使用索引的第一个列:如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引。这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引。(28)用UNION-ALL 替换UNION ( 如果有可能的话):当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序。如果用UNION ALL替代UNION, 这样排序就不是必要了。效率就会因此得到提高。需要注意的是,UNION ALL 将重复输出两个结果集合中相同记录。因此各位还是要从业务需求分析使用UNION ALL的可行性. UNION 将对结果集合排序,这个操作会使用到SORT_AREA_SIZE这块内存。对于这块内存的优化也是相当重要的。下面的SQL可以用来查询排序的消耗量:
低效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
高效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION ALL
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
(29)用WHERE替代ORDER BY:ORDER BY 子句只在两种严格的条件下使用索引。ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序。ORDER BY中所有的列必须定义为非空。WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列。例如: 表DEPT包含以下列:DEPT_CODE PK NOT NULLDEPT_DESC NOT NULLDEPT_TYPE NULL低效: (索引不被使用)SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE高效: (使用索引)SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0(30)避免改变索引列的类型:当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换。 假设 EMPNO是一个数值类型的索引列:SELECT … FROM EMP WHERE EMPNO = ‘123'。 实际上,经过Oracle类型转换, 语句转化为: SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123') 。幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变。现在,假设EMP_TYPE是一个字符类型的索引列:SELECT … FROM EMP WHERE EMP_TYPE = 123 。这个语句被Oracle转换为: SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123。因为内部发生的类型转换, 这个索引将不会被用到! 为了避免Oracle对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来。注意当字符和数值比较时, Oracle会优先转换数值类型到字符类型。(31)需要当心的WHERE子句:某些SELECT 语句中的WHERE子句不使用索引。这里有一些例子:(1)‘!=' 将不使用索引。记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中。(2)‘||'是字符连接函数。就象其他函数那样, 停用了索引。(3)‘+'是数学函数。就象其他数学函数那样, 停用了索引。(4)相同的索引列不能互相比较,这将会启用全表扫描。(32)a. 如果检索数据量超过30%的表中记录数.使用索引将没有显着的效率提高。b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别。而通常情况下,使用索引比全表扫描要块几倍乃至几千倍!(33)避免使用耗费资源的操作:带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎执行耗费资源的排序(SORT)功能。DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑的, 毕竟它们的可读性很强。(34)优化GROUP BY:提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉。下面两个查询返回相同结果但第二个明显就快了许多。
低效:
SELECT JOB, AVG(SAL)
FROM EMP
GROUP JOB
HAVING JOB = 'PRESIDENT'
OR JOB = 'MANAGER'高效:
SELECT JOB, AVG(SAL)
FROM EMP
WHERE JOB = 'PRESIDENT'
OR JOB = 'MANAGER'
GROUP JOB

2. sql 请阐述为什么应该尽量减少“SELECT *”这类语句的使用

SELECT--SQL语法
从一个或多个表中检索数据。SELECT SQL 命令是与其它 Vfp一样的内置的 Vfp命令。当你使用 SELECT 来生成查询时, Vfp翻译查询并从表中获取指定数据。你可以从以下地方创建 SELECT 查询:

“命令”窗口中
带有其它任何 Vfp命令的 Vfp程序中
查询设计器中
SELECT [ALL | DISTINCT] [TOP nExpr [PERCENT]] [Alias.] Select_Item
[[AS] Column_Name] [, [Alias.] Select_Item [[AS] Column_Name] ...]
FROM [FORCE] [DatabaseName!] Table [[AS] Local_Alias]
[ [INNER | LEFT [OUTER] | RIGHT [OUTER] | FULL [OUTER] JOIN DatabaseName!]
Table [[AS] Local_Alias] [ON JoinCondition ...]
[[INTO Destination] | [TO FILE FileName [ADDITIVE] | TO PRINTER [PROMPT] | TO SCREEN]]
[PREFERENCE PreferenceName] [NOCONSOLE] [PLAIN] [NOWAIT]
[WHERE JoinCondition [AND JoinCondition ...] [AND | OR FilterCondition [AND | OR FilterCondition ...]]]
[Group By GroupColumn [, GroupColumn ...]] [HAVING FilterCondition] [UNION [ALL] SELECTCommand]
[Order By Order_Item [ASC | DESC] [, Order_Item [ASC | DESC] ...]]
参数
SELECT
在 SELECT 子句中指定在查询结果中包含的字段、常量和表达式。
ALL
查询结果中包含所有行 ( 包括重复值 )。ALL 是默认设置。
DISTINCT
在查询结果中剔除重复的行。每一个 SELECT 子句只能使用一次 DISTINCT。
TOP nExpr [PERCENT]
在符合查询条件的所有记录中,选取指定数量或百分比的记录。TOP 子句必须与 ORDER BY 子句同时使用。ORDER BY 子句指定查询结果中包含的列上由Top字句决定的行数, TOP 子句根据此排序选定最开始的 nExpr个或 nExpr% 的记录。

您可以指定选取 1 到 32767 个记录。使用 ORDER BY 子句指定的字段进行排序,会产生并列的情况,比如,可能有多个记录,它们在选定的字段上相同;所以,如果您指定 nExpr 为 10,在查询结果中可能多于 10 个记录,因为可能有几个记录位置并列。

如果包含 PERCENT 关键字指定查询结果中的记录数,得到记录数的可能是小数,这时进行取整。包含 PERCENT 关键字时,nExpr 的范围是 0.01 到 99.99。

[Alias.] Select_Item
限定匹配项的名称。Select_Item 指定的每一项在查询结果中都生成一列。一个项可以是以下一个
FROM 子句所包含的表中的字段名称。
一个常量,查询结果中每一行都出现这个常量值。
一个表达式,可以是用户自定义函数名。
关于使用用户定义函数的详细信息, 参见注释节中的带用户定义函数的 SELECT。

你用 Select_Item 指定的各项生成一个查询结果列。

如果两个或更多的项具有相同的名称, 在项名前包含表别名和一个句点来避免列重复。

[AS] Column_Name
为查询输出中的列指定显示名。Column_Name 可以是表达式但不能包含不允许的字符, 如, 字段名中的空格。
当 Select_Item 是一个表达式或包含一个字段函数而且你想给该列一个有意义的名字时该选项是有用的。

FROM [FORCE] DatabaseName!
列出所有从中检索数据的表。
FORCE 指定连接表时按它们出现在 FROM 子句中的顺序。如果省略 FORCE, Vfp会试图对查询进行优化。但是, 使用 FORCE 子句,避免了优化过程,可能加快查询执行的速度。

当包含表的数据库不是当前数据库时,DatabaseName! 指定这个数据库的名称。如果数据库不是当前数据库,就必须指定包含表的数据库名称。应在数据库名称之后表名之前加上感叹号(!)分隔符。

[[AS] Local_Alias]
为 Table 中的表指定一个临时名称。如果指定了本地别名,那么在整个SELECT 语句中必须都用这个别名代替表名。本地别名不影响 Visual FoxPro环境。INNER JOIN 只有在其他表中包含对应记录(一个或多个)的记录才出现在查询结果中。
INNER JOIN 只有在其他表中包含对应记录(一个或多个)的记录才出现在查询结果中。

LEFT [OUTER] JOIN 在查询结果中包含:JOIN 左侧表中的所有记录,以及JOIN 右侧表中匹配的记录。OUTER 关键字可被省略;包含 OUTER 强调这是一个外连接 (outer join)。

RIGHT [OUTER] JOIN 在查询结果中包含:JOIN 右侧表中的所有记录,以及 JOIN 左侧表中匹配的记录。OUTER 关键字可被省略;包含 OUTER 强调这是一个外连接接 (outer join)。

FULL [OUTER] JOIN 在查询结果中包含:JOIN 两侧所有的匹配记录,和不匹配的记录;包含 OUTER 强调这是一个外连接 (outer join)。

关于连接的详细信息, 参见备注段中的 Joins。

ON JoinCondition 指定连接条件。

INTO Destination
指定在何处保存查询结果。Destination 可以是下列子句之一:
ARRAY ArrayName ,将查询结果保存到变量数组中。
如果查询结果中不包含任何记录,则不创建这个数组。

CURSOR CursorName [NOFILTER | READWRITE] 将查询结果保存到临时表中。
要创建一个查用于子查询中的游标, 用 NOFILTER。关于 NOFILTER 的详细信息, 参见备注节。

要指定游标是临时的和可修改的, 使用 READWRITE。如果源表或表使用 autoincrementing, 该设置不会被 READWRITE 游标继承。

DBF | TABLE TableName [DATABASE DatabaseName [NAME LongTableName]] 保存查询结果到一个表中。
包含 DATABASE DatabaseName 以指定添加了表的数据库。

包含 NAME LongTableName 可以为该表命一个最多可包括 128 个字符的并且可以在数据库中代替短名字的长名。

如果没有包括 INTO 子句, 查询结果显示在一个“浏览”窗口中。也可以用 TO FILE 子句来定向查询结果到打印机或一个文件。

TO FILE FileName [ADDITIVE] | TO PRINTER [PROMPT] | TO SCREEN
定向查询结果到打印机或一个文件。
ADDITIVE 添加查询输出到 TO FILE FileName 中指定的已存在的文本文件内容中。

TO PRINTER 定向查询输出到一个打印机。在打印开始之前,使用可选的 PROMPT 子句显示一个对话框。您可以根据当前安装的打印机驱动程序调整打印机的设置。将 PROMPT 子句放置在紧跟 TO PRINTER 之后。

TO SCREEN 使查询结果定向输出到 Vfp主窗口或活动的用户自定义窗口中。

PREFERENCE PreferenceName
如果查询结果送往浏览窗口,就可以使用 PREFERENCE 保存浏览窗口的属性和选项以备后用。关于 PREFERENCE 功能的详细信息, 参见备注节。
NOCONSOLE
不显示送到文件、打印机或 Vfp主窗口的查询结果。
PLAIN
防止列标题出现在显示的查询结果中。不管有无 TO 子句都可使用 PLAIN子句。如果 SELECT 语句中包括 INTO 子句,则忽略 PLAIN 子句。
NOWAIT
打开浏览窗口并将查询结果输出到这个窗口后继续程序的执行。程序并不等待关闭浏览窗口,而是立即执行紧接在 SELECT 语句后面的程序行。关于如何使用 NOWAIT 的说明, 参见备注节。
WHERE JoinCondition
指定 Vfp的查询结果中只包括符合指定条件的记录。JoinCondition 指定位于 FROM 子句中的字段连接表。关于指定连接条件的详细信息, 参见备注节。
WHERE 支持 JoinCondition 的 ESCAPE 操作符, 让你可以执行包含有百分号 (%) 和下划线 (_) 通配符的 SELECT SQL 命令查询。ESCAPE 允许你指定一个按原字样处理的 SELECT SQL 命令通配符。在 ESCAPE 子句中, 一旦一个字符被放到通配符字符之前,就表示这个通配符被看作一个文字字符。

FilterCondition
指定将包含在查询结果中记录必须符合的条件。使用 AND 或 OR 操作符,您可以包含随意数目的过滤条件。您还可以使用 NOT 操作符将逻辑表达式的值取反,或使用 EMPTY() 函数以检查空字段。
SELECT SQL 命令在筛选条件中支持 "<field> IS / IS NOT NULL"。要学习如何使用 FilterCondition。

Group By GroupColumn [, GroupColumn ...]
按列的值对查询结果的行进行分组。GroupColumn 可以是常规的表字段名,也可以是一个包含 SQL 字段函数的字段名,还可以是一个数值表达式,指定查询结果表中的列位置(最左边的列编号为 1 )。
HAVING FilterCondition
指定包括在查询结果中的组必须满足的筛选条件。HAVING 应该同 GROUP BY一起使用。它能包含数量不限的筛选条件,筛选条件用 AND 或 OR 连接,还可以使用 NOT 来对逻辑表达式求反。可以在 HAVING 子句中使用本地别名和字段函数。 关于你可以使用的字段函数的详细信息, 参见备注节。FilterCondition 不能包含子查询。
可以使用带 HAVING 子句的 Group By。使用 HAVING 子句的命令如果没有使用 GROUP BY 子句,则它的作用与WHERE 子句相同。
如果 HAVING 子句不包含字段函数的话,使用 WHERE 子句可以获得较快的速度。

HAVING 子句应该出现在 INTO 子句前否则产生错误。

[UNION [ALL] SELECTCommand]
把一个 SELECT 语句的最后查询结果同另一个 SELECT 语句最后查询结果组合起来。默认情况下,UNION 检查组合的结果并排除重复的行。
要组合多个UNION 子句,可使用括号。可以用 UNION 子句模拟一个外部联接。
ALL 防止 UNION 删除组合结果中重复的行。

当一个列是备注或通用型时, 不允许连接不同类型的列。

在 Vfp8.0 以前的版本中, 当在两个不同类型的字段上执行 UNION 操作时你需要执行明确的转换。
Vfp现在对支持它的数据类型支持隐含数据类型转换。关于隐含数据类型转换和数据类型优先, UNION 子句允许的规则, 以及其它信息的详细内容, 参见备注节中的数据类型转换和优先。

Order By Order_Item [ASC | DESC]
根据列的数据对查询结果进行排序。每个 Order_Item 都必须对应查询结果中的一列。它可以是下列之一:
FROM 子句中表的字段,同时也是 SELECT 主句(不在子查询中)的一个选择项。
一个数值表达式,表示查询结果中列的位置(最左边列编号为 1 )。
ASC 指定查询结果根据排序项以升序排列。它是 ORDER BY 的默认选项。

DESC 指定查询结果以降序排列。

备注
在使用 FROM 子句时如果没有打开表, Vfp显示“打开”对话框让你指定文件位置。一但打开后, 表在查询完成后仍然保持打开。

当在 Destination 参数中使用 CURSOR 子句时, 如果你指定了一个打开的表的名字, Vfp产生一条错误信息。在 SELECT 执行后, 临时游标保持打开并是活动的和只读的除非你指定了 READWRITE 选项。当你关闭该临时游标时, 它被删除。游标可以指定 SORTWORK 而成为存在于驱动器或卷上的临时文件。

当在 Destination 参数中使用 CURSOR 子句时, 你现在可以使用 NOFILTER 来创建一个可用于后来的查询的游标。在早期版本的 Vfp中, 你需要包括一个额外的常数或表达式作为筛选。例如, 添加一个逻辑 true 作为筛选表达式来创建一个可用于后来的查询的查询:

SELECT *, .T. FROM customers INTO CURSOR myquery
但是, 包括 NOFILTER 会降低查询性能因为要在磁盘上创建一个临时表。临时表在游标关闭时从磁盘上删除。

当在 Destination 参数中使用 DBF | TABLE 子句时, 如果你指定了一个已经打开的表, 而且 SET SAFETY 是设置为 OFF, Vfp不警告地复写该表。如果你没有指定一个扩展名, Vfp给表一个 .dbf 扩展名。在 SELECT 执行后表保持打开并且是活动的。

如果你在相同查询中包括 INTO 和 TO 子句, Vfp忽略 TO 子句。如果你包括 TO 子句但没有包括 INTO 子句, 你可以定向查询结果到一个名为 FileName 的 ASCII 文本文件, 到打印机, 或到 Vfp主窗口。

PREFERENCE 把特征, 属性或参数选项长期保存在 FoxUser.dbf 资源文件中。Preferences 可以在任何时候获取。第一次执行有 PREFERENCE Preference Name 的 SELECT 命令时创建参数选项。以后执行有相同参数选项名的 SELECT 命令时便将浏览窗口恢复到原来的参数选项状态。当浏览窗口关闭时,更新参数选项。如果您按下 CTRL+Q+W 键退出“浏览”窗口,您对“浏览”窗口所做的更改不会保存到资源文件中。

SELECT 命令中包括 TO SCREEN 可以把查询结果定向输出到 Vfp主窗口或用户自定义窗口。如果显示时 Vfp主窗口或用户自定义窗口中写满了一屏,就暂停输出。按任意键可以查看查询结果后面的内容。但是,如果命令中包括了 NOWAIT 子句,显示查询结果时就不会暂停,等待按键,而是在 Vfp主窗口或用户自定义窗口中连续滚过所有内容。如果命令中包含有 INTO 子句,忽略 NOWAIT 子句。

在一个 SQL 查询的 WHERE 子句中包括 EVALUATE() 函数会返回不正确的数据。

如果包括一个以上的表在查询中, 你应该在第一个以后为每一个表指定一个连接条件。连接条件可以包含筛选条件。

注意 每一个 SELECT 语句的最大连接数是 9.
必须用 AND 操作符来连接多个连接条件。各连接条件具有以下格式:

当你在串中使用 = 操作符时, 它的动作根据 SET ANSI 的设置会不同。当 SET ANSI 设置为 OFF 时, Vfp只比较串到较短串结束。当 SET ANSI 设置为 ON 时, Vfp遵循 ANSI 标准的字符串比较。关于 Vfp如果执行字符串比较的额外信息, 参见 SET ANSI 和 SET EXACT。

下列字段函数可以与选定项一起使用,选定项可以是一个字段或包含字段的表达式:

AVG(Select_Item), 计算列中数值的平均值。
COUNT(Select_Item), 计算列中选定项的数目。计算查询输出的行数。COUNT(*) 计算查询输出中的行数。
MIN(Select_Item), 确定列中 Select_Item 的最小值。
MAX(Select_Item), 确定列中 Select_Item 的最大值。
SUM(Select_Item), 计算列中数值的和。
字段函数不能嵌套使用。

UNION 子句遵守下列规则:

不能使用 UNION 来组合子查询。
两个 SELECT 命令的查询结果中的列数必须相同。
两个 SELECT 查询结果中的对应列必须有相同的数据类型和宽度。
只有最后的 SELECT 中可以包含 ORDER BY 子句,而且必须按编号指出所输出的列。如果包含了一个 ORDER BY 子句,它将影响整个结果。
当你用 UNION 连接查询中的两个表时, 仅匹配连接字段值的记录会出现在查询结果中。如果在父表中的记录在子表中没有相应的记录, 父表中的记录不会出现在查询结果中。一个外部联接允许你包括父表中的所有记录到输出结果中, 连同子表中的匹配记录一起。要在 Vfp中创建一个外部联接, 你需要要使用一个嵌套的 SELECT 命令
注意 确信在每一个分号前包括一个空格。否则, Vfp产生一个错误。
上例中, 在 UNION 子句前的部分的命令从两个表中选择具有匹配值的记录。不包括没有相关的发票的客户公司。命令中 UNION 子句后的部分选择客户表中的在订单表中无匹配记录的记录。

关于第二部分的命令, 注意以下几点:

包括在园括号中的 SELECT 语句首先处理。该语句的结果是选择订单表中的所有客户编号。
WHERE 子句找出 customer 表中的在 orders 表没有相关记录的所有客户编号。由于第一节中的命令提供了所在 orders 表中有客户编号的公司, Customer 表中的所有公司现在都包含在查询结果中了。
因为在 UNION 中的表的结构必须相同, 有两个占位符在第二个 SELECT 语句中来代表第一个 SELECT 语句中的 orders.order_id 和 orders.emp_id。
注意 占位符必须与它们所代表的字段有相同类型。如果字段是日期型, 占位符应该是 。如果字段是一个字符字段, 占位符应该是一个空串 ("")。

如果你没有在 Order By 子句中指定排序, 查询结果显示为未排序。

当你发出 SET TALK ON 并执行 SELECT 时, Vfp显示查询使用的时间和结果中的记录数。 _TALLY 包含了在查询结果中的记录数。

SET FILTER 设置的筛选条件对 SELECT 命令不起作用。

注意 下面部分提到的子查询, 是指在 SELECT 命令中包含的 SELECT 命令。子查询必须包括在园括号中。在 SELECT 命令的 WHERE 子句中可以包含最多两个平级的(非嵌套)的子查询。子查询中可以有多个连接条件 (join conditions)。
在你创建查询输出时, 列的命名遵循如下规则:

如果选择项是具有唯一名称的字段,则用字段名作为输出列名。
如果多个选择项具有相同名称。例如,如果名为 Customer 的表有一个STREET 字段,而名为 Employees 的表也有一个 STREET 字段,则输出列命名为 Extension_A 和 Extension_B (STREET_A 和 STREET_B)。如果选择项名称有 10 字符长,可以将名称截短后再加下划线和字母。例如,DEPARTMENT 变为 DEPARTME_A。
如果选择项是表达式,它的输出列命名为 EXP_A。其他表达式分别命名为EXP_B、EXP_C,依此类推。
如果选择项包含诸如 COUNT() 这样的字段函数,则输出列命名为CNT_A。如果另一个选择项包含 SUM(),它的输出列命名为 SUM_B。
用户定义函数和 在 SELECT 子句中使用用户自定义函数有明显优点,但使用时应考虑以下限制:

SELECT 子句的运行速度会受用户自定义函数执行速度的影响。因此,如果使用户自定义函数的操作量很大,则这些函数的功能最好调用 C 语言或汇编语言编写的 API 或用户自定义函数来完成。
在 SELECT 激活的用户自定义函数中,很难预测 Vfp输入/输出(I/O)和表的环境。一般来说,不知道选择的工作区是哪一个,不知道当前表的名称,甚至不知道正在处理的字段名。这些变量的值完全取决于用户自定义函数在优化过程的什么地方激活。
在 SELECT 子句调用的用户自定义函数中修改 VfpI/O 或表的环境是很不安全的。一般来说,这样做的结果难以预料。
从 SELECT 将值传递给用户自定函数唯一可靠的方法,是激活用户自定义函数时以参数的形式传递。
经过实践,有可能发现某种被认为是违法的操作在某种 FoxPro 版本中运行正确,但这并不保证它在以后的版本中也能正确运行。
抛开这些限制不说,用户自定义函数在 SELECT 语句中还是可接受的。但不要忘记使用 SELECT 可能要降低性能。要学习如何在 SELECT 中使用用户定义函数, 参见示例节。

连接 Vfp支持 ANSI SQL '92 连接 (Join) 语法,通过比较两个或多个表中的字段,将它们的记录连接到一起,生成查询。例如,内部连接 (inner join) 是将两个表中连接字段 (joined field) 值相同的记录选取到查询中。Vfp支持嵌套连接(nested joins)

由于 SQL 是派生于数学集合理论, 各表可以代表一个环。指定连接条件的 ON 子句确定交接点, 它代表匹配的行集合。对于一个内部联接, 交接发生在两个环的内部或 "inner" 部分。一个外联接不仅仅包括这些表内部的交叉区域匹配的行, 也包括环的外面的左或右部的交集的行。

3. 为什么存储过程执行速度比普通的SQL快而且减少网络流量

存储过程所以快是因为他是预先编译的,当然节省了编译的时间。减少网络流量是指减少与客户端之间的交互,在服务器上执行运算,最后只把结果反给客户端,所以流量少。

比如你查询个内容,需要先查一个表,根据结果再查另外一个表。不用存储过程你怎么做呢?自然是先读出那个表的内容来,然后在asp/asp.net/php里,用代码生成一个语句再去查询,这样要往复2,3次。而用存储过程就可以直接在服务器上运算,只要一次来回就ok了,自然网络流量就减少

因为在存储过程中的SQL语句是已经经过了语法检查和编译的,可以直接执行;而SQL总要先进行语法解析和编译才能执行。另外对于网络执行的话,执行相同的任务,客户端调用存储过程的代码传输量和直接执行SQL语句相比也要更少。

4. 为什么应该尽量减少“SELECT *”这类语句的使用

因为使用select * 会将所有字段的值全都取出,会增加数据的冗余,如果用于网站数据的话,会增加服务器的负担。因此尽量明确需要查询的字段值。

个人见解。希望有所帮助。

5. 如何优化SQL语句

一、问题的提出
在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统不是简单地能实现其功能就可,而是要写出高质量的SQL语句,提高系统的可用性。
在多数情况下,Oracle使用索引来更快地遍历表,优化器主要根据定义的索引来提高性能。但是,如果在SQL语句的where子句中写的SQL代码不合理,就会造成优化器删去索引而使用全表扫描,一般就这种SQL语句就是所谓的劣质SQL语句。在编写SQL语句时我们应清楚优化器根据何种原则来删除索引,这有助于写出高性能的SQL语句。
二、SQL语句编写注意问题
下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍。在这些where子句中,即使某些列存在索引,但是由于编写了劣质的SQL,系统在运行该SQL语句时也不能使用该索引,而同样使用全表扫描,这就造成了响应速度的极大降低。
1.
IS
NULL

IS
NOT
NULL
不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。
任何在where子句中使用is
null或is
not
null的语句优化器是不允许使用索引的。
2.
联接列
对于有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的。我们一起来看一个例子,假定有一个职工表(employee),对于一个职工的姓和名分成两列存放(FIRST_NAME和LAST_NAME),现在要查询一个叫比尔.克林顿(Bill
Cliton)的职工。
下面是一个采用联接查询的SQL语句,
select
*
from
employss
where
first_name||''||last_name
='Beill
Cliton';
上面这条语句完全可以查询出是否有Bill
Cliton这个员工,但是这里需要注意,系统优化器对基于last_name创建的索引没有使用。
当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引。
***
where
first_name
='Beill'
and
last_name
='Cliton';
.
带通配符(%)的like语句
同样以上面的例子来看这种情况。目前的需求是这样的,要求在职工表中查询名字中包含cliton的人。可以采用如下的查询SQL语句:
select
*
from
employee
where
last_name
like
'%cliton%';
这里由于通配符(%)在搜寻词首出现,所以Oracle系统不使用last_name的索引。在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。在下面的查询中索引得到了使用:
select
*
from
employee
where
last_name
like
'c%';
4.
Order
by语句
ORDER
BY语句决定了Oracle如何将返回的查询结果排序。Order
by语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)。任何在Order
by语句的非索引项或者有计算表达式都将降低查询速度。
仔细检查order
by语句以找出非索引项或者表达式,它们会降低性能。解决这个问题的办法就是重写order
by语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在order
by子句中使用表达式。
5.
NOT
我们在查询时经常在where子句使用一些逻辑表达式,如大于、小于、等于以及不等于等等,也可以使用and(与)、or(或)以及not(非)。NOT可用来对任何逻辑运算符号取反。下面是一个NOT子句的例子:
...
where
not
(status
='VALID')
如果要使用NOT,则应在取反的短语前面加上括号,并在短语前面加上NOT运算符。NOT运算符包含在另外一个逻辑运算符中,这就是不等于(<>)运算符。换句话说,即使不在查询where子句中显式地加入NOT词,NOT仍在运算符中,见下例:
...
where
status
<>'INVALID';
对这个查询,可以改写为不使用NOT:
select
*
from
employee
where
salary<3000
or
salary>3000;
虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。
虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。

6. 如何能缩短sql语句的执行时间

1. SQL优化的原则是:将一次操作需要读取的BLOCK数减到最低,即在最短的时间达到最大的数据吞吐量。
调整不良SQL通常可以从以下几点切入:
? 检查不良的SQL,考虑其写法是否还有可优化内容
? 检查子查询 考虑SQL子查询是否可以用简单连接的方式进行重新书写
? 检查优化索引的使用
? 考虑数据库的优化器

2. 避免出现SELECT * FROM table 语句,要明确查出的字段。

3. 在一个SQL语句中,如果一个where条件过滤的数据库记录越多,定位越准确,则该where条件越应该前移。

4. 查询时尽可能使用索引覆盖。即对SELECT的字段建立复合索引,这样查询时只进行索引扫描,不读取数据块。

5. 在判断有无符合条件的记录时建议不要用SELECT COUNT (*)和select top 1 语句。

6. 使用内层限定原则,在拼写SQL语句时,将查询条件分解、分类,并尽量在SQL语句的最里层进行限定,以减少数据的处理量。

7. 应绝对避免在order by子句中使用表达式。

8. 如果需要从关联表读数据,关联的表一般不要超过7个。

9. 小心使用 IN 和 OR,需要注意In集合中的数据量。建议集合中的数据不超过200个。

10. <> 用 < 、 > 代替,>用>=代替,<用<=代替,这样可以有效的利用索引。

11. 在查询时尽量减少对多余数据的读取包括多余的列与多余的行。

12. 对于复合索引要注意,例如在建立复合索引时列的顺序是F1,F2,F3,则在where或order by子句中这些字段出现的顺序要与建立索引时的字段顺序一致,且必须包含第一列。只能是F1或F1,F2或F1,F2,F3。否则不会用到该索引。

13. 多表关联查询时,写法必须遵循以下原则,这样做有利于建立索引,提高查询效率。格式如下select sum(table1.je) from table1 table1, table2 table2, table3 table3 where (table1的等值条件(=)) and (table1的非等值条件) and (table2与table1的关联条件) and (table2的等值条件) and (table2的非等值条件) and (table3与table2的关联条件) and (table3的等值条件) and (table3的非等值条件)。
注:关于多表查询时from 后面表的出现顺序对效率的影响还有待研究。

14. 子查询问题。对于能用连接方式或者视图方式实现的功能,不要用子查询。例如:select name from customer where customer_id in ( select customer_id from order where money>1000)。应该用如下语句代替:select name from customer inner join order on customer.customer_id=order.customer_id where order.money>100。

15. 在WHERE 子句中,避免对列的四则运算,特别是where 条件的左边,严禁使用运算与函数对列进行处理。比如有些地方 substring 可以用like代替。

16. 如果在语句中有not in(in)操作,应考虑用not exists(exists)来重写,最好的办法是使用外连接实现。

17. 对一个业务过程的处理,应该使事物的开始与结束之间的时间间隔越短越好,原则上做到数据库的读操作在前面完成,数据库写操作在后面完成,避免交叉。

18. 请小心不要对过多的列使用列函数和order by,group by等,谨慎使用disti软件开发t。

19. 用union all 代替 union,数据库执行union操作,首先先分别执行union两端的查询,将其放在临时表中,然后在对其进行排序,过滤重复的记录。
当已知的业务逻辑决定query A和query B中不会有重复记录时,应该用union all代替union,以提高查询效率。

数据更新的效率
1. 在一个事物中,对同一个表的多个insert语句应该集中在一起执行。
2. 在一个业务过程中,尽量的使insert,update,delete语句在业务结束前执行,以减少死锁的可能性。

数据库物理规划的效率

为了避免I/O的冲突,我们在设计数据库物理规划时应该遵循几条基本的原则(以ORACLE举例):
?? table和index分离:table和index应该分别放在不同的tablespace中。

?? Rollback Segment的分离:Rollback Segment应该放在独立的Tablespace中。

?? System Tablespace的分离:System Tablespace中不允许放置任何用户的object。(mssql中primary filegroup中不允许放置任何用户的object)

?? Temp Tablesace的分离:建立单独的Temp Tablespace,并为每个user指定default Temp Tablespace

??避免碎片:但segment中出现大量的碎片时,会导致读数据时需要访问的block数量的增加。对经常发生DML操作的segemeng来说,碎片是不能完全避免的。所以,我们应该将经常做DML操作的表和很少发生变化的表分离在不同的Tablespace中。

当我们遵循了以上原则后,仍然发现有I/O冲突存在,我们可以用数据分离的方法来解决。
?? 连接Table的分离:在实际应用中经常做连接查询的Table,可以将其分离在不同的Taclespace中,以减少I/O冲突。

?? 使用分区:对数据量很大的Table和Index使用分区,放在不同的Tablespace中。

在实际的物理存储中,建议使用RAID。日志文件应放在单独的磁盘中。

7. SQL 语句优化,该怎么处理

(1)选择最有效率的表名顺序(只在基于规则的优化器中有效):
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写
在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的
情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询
, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其
他表所引用的表.
(2) WHERE子句中的连接顺序.:
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必
须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE
子句的末尾.
(3) SELECT子句中避免使用‘ * ‘:
ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过
查询数据字典完成的, 这意味着将耗费更多的时间
(4)减少访问数据库的次数:
ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变
量 , 读数据块等;
(5)在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加
每次数据库访问的检索数据量 ,建议值为200
(6)使用DECODE函数来减少处理时间:
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.
(7)整合简单,无关联的数据库访问:
如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使
它们之间没有关系)
(8)删除重复记录:
最高效的删除重复记录方法 ( 因为使用了ROWID)例子:
DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X WHERE X.EMP_NO = E.EMP_NO);
(9)用TRUNCATE替代DELETE:
当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存
放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前
的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回
滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的
资源被调用,执行时间也会很短. (译者按: TRUNCATE只在删除全表适
用,TRUNCATE是DDL不是DML)
(10)尽量多使用COMMIT:
只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也
会因为COMMIT所释放的资源而减少:
COMMIT所释放的资源:
a. 回滚段上用于恢复数据的信息.
b. 被程序语句获得的锁
c. redo log buffer 中的空间
d. ORACLE为管理上述3种资源中的内部花费
(11)用Where子句替换HAVING子句:
避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行
过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,
那就能减少这方面的开销. (非oracle中)on、where、having这三个都可以加条
件的子句中,on是最先执行,where次之,having最后,因为on是先把不符合条
件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该
速度是最快的,where也应该比having快点的,因为它过滤数据后才进行sum,在
两个表联接时才用on的,所以在一个表的时候,就剩下where跟having比较了。
在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们
的结果是一样的,只是where可以使用rushmore技术,而having就不能,在速度
上后者要慢如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不
确定的,根据上篇写的工作流程,where的作用时间是在计算之前就完成的,而
having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。在多
表联接查询时,on比where更早起作用。系统首先根据各个表之间的联接条件,
把多个表合成一个临时表后,再由where进行过滤,然后再计算,计算完后再由
having进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条
件应该在什么时候起作用,然后再决定放在那里
(12)减少对表的查询:
在含有子查询的SQL语句中,要特别注意减少对表的查询.例子:
SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT
TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
(13)通过内部函数提高SQL效率.:
复杂的SQL往往牺牲了执行效率. 能够掌握上面的运用函数解决问题的方法
在实际工作中是非常有意义的
(14)使用表的别名(Alias):
当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column
上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.
(15)用EXISTS替代IN、用NOT EXISTS替代NOT IN:
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联
接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率. 在子查
询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是
最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN
,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS.
例子:
(高效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND EXISTS (SELECT
‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT
DEPTNO FROM DEPT WHERE LOC = ‘MELB')
(16)识别'低效执行'的SQL语句:
虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具
来解决问题始终是一个最好的方法:
SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-
DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2)
Reads_per_run,
SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND
(BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC;
(17)用索引提高效率:
索引是表的一个概念部分,用来提高检索数据的效率,ORACLE使用了一个复
杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当ORACLE找
出执行查询和Update语句的最佳路径时, ORACLE优化器将使用索引. 同样在联结
多个表时使用索引也可以提高效率. 另一个使用索引的好处是,它提供了主键
(primary key)的唯一性验证.。那些LONG或LONG RAW数据类型, 你可以索引几乎
所有的列. 通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小
表时,使用索引同样能提高效率. 虽然使用索引能得到查询效率的提高,但是我们
也必须注意到它的代价. 索引需要空间来存储,也需要定期维护, 每当有记录在
表中增减或索引列被修改时, 索引本身也会被修改. 这意味着每条记录的INSERT
, DELETE , UPDATE将为此多付出4 , 5 次的磁盘I/O . 因为索引需要额外的存
储空间和处理,那些不必要的索引反而会使查询反应时间变慢.。定期的重构索引
是有必要的.:
ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
(18)用EXISTS替换DISTINCT:
当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在
SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换, EXISTS 使查询更为迅
速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果. 例子:
(低效): SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E
WHERE D.DEPT_NO = E.DEPT_NO (高效): SELECT DEPT_NO,DEPT_NAME FROM DEPT
D WHERE EXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
(19) sql语句用大写的;因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行
(20)在java代码中尽量少用连接符“+”连接字符串!

8. 怎么用delphi+SQL语句实现sql里数据减少

有几种方法可以实现,一种是当你在edit2中输入数量,按确定后,执行
update 库存表 set 数量=数量-strtoint(trim(edit2.text);
还有一种就是在出仓表中创建insert触发器,当有新的出仓记录时会自动减少相应的库存

9. SQL语句能直接操作一张表的某个值加1,或者减1么具体语句应该怎么写

sql语句将一个表的某个值加1或减1,直接用update语句即可。

工具:mysql 5.6

步骤:

1、如图,student表中有如下数据:

10. 为什么静态sql语句会减少软解析

深入shared pool

解析SQL语句

生成执行计划

中间考虑的因素很多,包括访问的对象的存在、权限、等等

执行SQL语句

解析的过程(生成最优执行计划)是一个耗费资源的过程,随着用户的并发数量的增加。数据库的性能也会降低的很快。

ORCLE对解析的执行
1、ORACLE将SQL语句分成为两个部分:静态部分+动态部分
2、静态部分:SQL 语句的关键词(所涉及的表名称、列名称、等)
3、动态部分:字面值(表里面的表数据,例如 where name=‘xkj’中的xkj)
静态部分是有限的、动态部分是无限的

绑定变量:实现SQL共享(静态部分),减少解析。在实际中,不同的SQL语句的静态部分的重复率非常的高。实际上,动态部分对SQL语句的解析的影响可以忽略不计
通过使用绑定变量,用来提高SQL语句的缓存命中率(减少解析次数、减少sql缓存)

declare
v1 varchar2(10);
n1 int;
begin
n1:=1
select salary into v1 from test where id=n1;
end;

在上面的SQL语句中,使用了绑定变量n1,在解析的时候,使用的绑定变量。执行的时候,将字面值传入语句中。因此这样SQL语句的命中率将会提高。

ORCLE将解析过的SQL语句缓存在shared pool中,碰到相同的SQL语句再次执行的时候,ORACLE直接使用已经解析过的执行计划。
Shared pool缓存内容:SQL语句、执行计划、PL/SQL代码、PL/SQL机器码等

Shared pool细分
1、库缓存:最近执行的SQL语句、存储过程、函数、解析树、执行计划,最活跃部分
2、数据字典缓存:SQL执行过程中涉及的数据字典
递归调用:shared pool为生成执行计划,又进行了很多别的调用(如查询数据字典)