• 首页|
  • 社群
    文章 合集 問答
    學習
    課程 程式設計字典
    工具庫
    開發工具 網站源碼 PHP 函式庫 JS特效 網站素材 擴充插件
    AI工具
    休閒
    遊戲下載 遊戲教程
    搜尋
    繁体中文
    简体中文 English 繁体中文 日本語 한국어 Melayu Français Deutsch
    Login
    singup
    首頁 資料庫 mysql教程 SQL养成一个好习惯是一笔财富_MySQL

    SQL养成一个好习惯是一笔财富_MySQL

    WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
    WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
    Jun 01, 2016 pm 01:50 PM
    開發

    bitsCN.com

       做软件开发的,大部分人都离不开跟数据库打交道,特别是erp开发的,跟数据库打交道更是频繁,存储过程动不动就是上千行,如果数据量大,人员流动大,那么我么还能保证下一段时间系统还能流畅的运行吗?我么还能保证下一个人能看懂我么的存储过程吗?那么我结合公司平时的培训和平时个人工作经验和大家分享一下,希望对大家有帮助。

      要知道SQL语句,我想我们有必要知道SQL Server查询分析器怎么执行我们的SQL语句的,我们很多人会看执行计划,或者用Profiler来监视和调优查询语句或者存储过程慢的原因,但是如果我们知道查询分析器的执行逻辑顺序,下手的时候就胸有成竹,那么下手是不是有把握点呢?

      一、查询的逻辑执行顺序

      (1) FROM left_table

      (3) join_type JOIN right_table (2) ON join_condition

      (4) WHERE where_condition

      (5) GROUP BY group_by_list

      (6) WITH {cube | rollup}

      (7) HAVING having_condition

      (8) SELECT (9) DISTINCT (11) top_specification select_list

      (9) ORDER BY order_by_list

      标准的 SQL 的解析顺序为:

      (1) FROM 子句 组装来自不同数据源的数据

      (2) WHERE 子句 基于指定的条件对记录进行筛选

      (3) GROUP BY 子句 将数据划分为多个分组

      (4) 使用聚合函数进行计算

      (5) 使用HAVING子句筛选分组

      (6) 计算所有的表达式

      (7) 使用ORDER BY对结果集进行排序

      二、执行顺序

      1. FROM:对FROM子句中前两个表执行笛卡尔积生成虚拟表vt1

      2. ON: 对vt1表应用ON筛选器只有满足 join_condition 为真的行才被插入vt2

      3. OUTER(join):如果指定了 OUTER JOIN保留表(preserved table)中未找到的行将行作为外部行添加到vt2,生成t3,如果from包含两个以上表,则对上一个联结生成的结果表和下一个表重复执行步骤和步骤直接结束。

      4. WHERE:对vt3应用 WHERE 筛选器只有使 where_condition 为true的行才被插入vt4

      5. GROUP BY:按GROUP BY子句中的列列表对vt4中的行分组生成vt5

      6. CUBE|ROLLUP:把超组(supergroups)插入vt6,生成vt6

      7. HAVING:对vt6应用HAVING筛选器只有使 having_condition 为true的组才插入vt7

      8. SELECT:处理select列表产生vt8

      9. DISTINCT:将重复的行从vt8中去除产生vt9

      10. ORDER BY:将vt9的行按order by子句中的列列表排序生成一个游标vc10

      11. TOP:从vc10的开始处选择指定数量或比例的行生成vt11 并返回调用者

      看到这里,那么用过Linq to SQL的语法有点相似啊?如果我们我们了解了SQL Server执行顺序,那么我们就接下来进一步养成日常SQL的好习惯,也就是在实现功能的同时有考虑性能的思想,数据库是能进行集合运算的工具,我们应该尽量的利用这个工具,所谓集合运算实际就是批量运算,就是尽量减少在客户端进行大数据量的循环操作,而用SQL语句或者存储过程代替。

      三、只返回需要的数据

      返回数据到客户端至少需要数据库提取数据、网络传输数据、客户端接收数据以及客户端处理数据等环节,如果返回不需要的数据,就会增加服务器、网络和客户端的无效劳动,其害处是显而易见的,避免这类事件需要注意:

      A、横向来看

      (1) 不要写SELECT * 的语句,而是选择你需要的字段。

      (2) 当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上。这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。

      1

      如有表table1(ID,col1)和table2(ID,col2)

      1

      Select A.ID, A.col1, B.col2

      2

      -- Select A.ID, col1, col2 –不要这么写,不利于将来程序扩展

      3

      from table1 A inner join table2 B on A.ID=B.ID Where …

      B、纵向来看

      (1) 合理写WHERE子句,不要写没有WHERE的SQL语句。

      (2) SELECT TOP N * -- 没有WHERE条件的用此替代。

      四、尽量少做重复的工作

      A、控制同一语句的多次执行,特别是一些基础数据的多次执行是很多程序员很少注意的。

      B、减少多次的数据转换,也许需要数据转换是设计的问题,但是减少次数是程序员可以做到的。

      C、杜绝不必要的子查询和连接表,子查询在执行计划一般解释成外连接,多余的连接表带来额外的开销。

      D、合并对同一表同一条件的多次UPDATE,比如

      UPDATE EMPLOYEE SET FNAME='HAIWER'

      WHERE EMP_ID=' VPA30890F'UPDATE EMPLOYEE SET LNAME='YANG'

      WHERE EMP_ID=' VPA30890F'

      这两个语句应该合并成以下一个语句

      UPDATE EMPLOYEE SET FNAME='HAIWER',LNAME='YANG'WHERE EMP_ID=' VPA30890F'

      E、UPDATE操作不要拆成DELETE操作+INSERT操作的形式,虽然功能相同,但是性能差别是很大的。

      五、注意临时表和表变量的用

      在复杂系统中,临时表和表变量很难避免,关于临时表和表变量的用法,需要注意:

      A、如果语句很复杂,连接太多,可以考虑用临时表和表变量分步完成。

      B、如果需要多次用到一个大表的同一部分数据,考虑用临时表和表变量暂存这部分数据。

      C、如果需要综合多个表的数据,形成一个结果,可以考虑用临时表和表变量分步汇总这多个表的数据。

      D、其他情况下,应该控制临时表和表变量的使用。

      E、关于临时表和表变量的选择,很多说法是表变量在内存,速度快,应该首选表变量,但是在实际使用中发现:

      (1) 主要考虑需要放在临时表的数据量,在数据量较多的情况下,临时表的速度反而更快。

      (2) 执行时间段与预计执行时间(多长)

      F、关于临时表产生使用SELECT INTO和CREATE TABLE + INSERT INTO的选择,一般情况下:

      SELECT INTO会比CREATE TABLE + INSERT INTO的方法快很多,

      但是SELECT INTO会锁定TEMPDB的系统表SYSOBJECTS、SYSINDEXES、SYSCOLUMNS,在多用户并发环境下,容易阻塞其他进程。

      所以我的建议是,在并发系统中,尽量使用CREATE TABLE + INSERT INTO,而大数据量的单个语句使用中,使用SELECT INTO。

      六、子查询的用法

      子查询是一个 SELECT 查询,它嵌套在 SELECT、INSERT、UPDATE、DELETE 语句或其它子查询中。

      任何允许使用表达式的地方都可以使用子查询,子查询可以使我们的编程灵活多样,可以用来实现一些特殊的功能。但是在性能上,往往一个不合适的子查询用法会形成一个性能瓶颈。如果子查询的条件中使用了其外层的表的字段,这种子查询就叫作相关子查询。

      相关子查询可以用IN、NOT IN、EXISTS、NOT EXISTS引入。 关于相关子查询,应该注意:

      (1) NOT IN、NOT EXISTS的相关子查询可以改用LEFT JOIN代替写法。比如:

      SELECT PUB_NAME FROM PUBLISHERS WHERE PUB_ID NOTIN (SELECT PUB_ID FROM TITLES WHERE TYPE ='BUSINESS')

      可以改写成:

      SELECT A.PUB_NAME FROM PUBLISHERS A LEFTJOIN TITLES B ON B.TYPE ='BUSINESS'AND A.PUB_ID=B. PUB_ID WHERE B.PUB_ID IS NULL

      比如NOT EXISTS:

      SELECT TITLE FROM TITLES

      WHERE NOT EXISTS

      (SELECT TITLE_ID FROM SALES WHERE TITLE_ID = TITLES.TITLE_ID)

      1

      可以改写成:

      SELECT TITLE

      FROM TITLES LEFTJOIN SALES

      ON SALES.TITLE_ID = TITLES.TITLE_ID

      WHERE SALES.TITLE_ID ISNULL

      2)如果保证子查询没有重复 ,IN、EXISTS的相关子查询可以用INNER JOIN 代替。比如:

      SELECT PUB_NAME

      FROM PUBLISHERS

      WHERE PUB_ID IN

      (SELECT PUB_ID

      FROM TITLES

      WHERE TYPE ='BUSINESS')

      1

      可以改写成:

      SELECT A.PUB_NAME --SELECT DISTINCT A.PUB_NAME

      FROM PUBLISHERS A INNERJOIN TITLES B

      ON B.TYPE ='BUSINESS'AND

      A.PUB_ID=B. PUB_ID

      (3) IN的相关子查询用EXISTS代替,比如:

      SELECT PUB_NAME FROM PUBLISHERS

      WHERE PUB_ID IN

      (SELECT PUB_ID FROM TITLES WHERE TYPE ='BUSINESS')

      可以用下面语句代替:

      SELECT PUB_NAME FROM PUBLISHERS WHERE EXISTS

      (SELECT1FROM TITLES WHERE TYPE ='BUSINESS'AND

      PUB_ID= PUBLISHERS.PUB_ID)

      4) 不要用COUNT(*)的子查询判断是否存在记录,最好用LEFT JOIN或者EXISTS,比如有人写这样的语句:

      SELECT JOB_DESC FROM JOBS

      WHERE (SELECTCOUNT(*) FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)=0

      应该改成:

      SELECT JOBS.JOB_DESC FROM JOBS LEFTJOIN EMPLOYEE

      ON EMPLOYEE.JOB_ID=JOBS.JOB_ID

      WHERE EMPLOYEE.EMP_ID ISNULL

      SELECT JOB_DESC FROM JOBS

      WHERE (SELECT COUNT(*) FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)0

      应该改成:

      SELECT JOB_DESC FROM JOBS

      WHEREEXISTS (SELECT 1 FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)

      七:尽量使用索引

      建立索引后,并不是每个查询都会使用索引,在使用索引的情况下,索引的使用效率也会有很大的差别。只要我们在查询语句中没有强制指定索引,索引的选择和使用方法是SQLSERVER的优化器自动作的选择,而它选择的根据是查询语句的条件以及相关表的统计信息,这就要求我们在写SQL语句的时候尽量使得优化器可以使用索引。为了使得优化器能高效使用索引,写语句的时候应该注意:

      (1)不要对索引字段进行运算,而要想办法做变换,比如:

      SELECT ID FROM T WHERE NUM/2=100

      应改为:

      SELECT ID FROM T WHERE NUM=100*2

      SELECT ID FROM T WHERE NUM/2=NUM1

      如果NUM有索引应改为:

      SELECT ID FROM T WHERE NUM=NUM1*2

      如果NUM1有索引则不应该改。

      (2)发现过这样的语句:

      SELECT 年,月,金额 FROM 结余表 WHERE100*年+月=2010*100+10

      1

      应该改为:

      SELECT 年,月,金额 FROM 结余表 WHERE 年=2010 AND 月=10

      (3)不要对索引字段进行格式转换

      日期字段的例子:

      WHERECONVERT(VARCHAR(10), 日期字段,120)='2010-07-15'

      应该改为

      WHERE日期字段〉='2010-07-15'AND 日期字段'2010-07-16'

      ISNULL转换的例子:

      WHEREISNULL(字段,'')''应改为:WHERE字段''

      WHEREISNULL(字段,'')=''不应修改

      WHEREISNULL(字段,'F') ='T'应改为: WHERE字段='T'

      WHEREISNULL(字段,'F')'T'不应修改

      (4) 不要对索引字段进行格式转换

      WHERELEFT(NAME, 3)='ABC' 或者WHERE SUBSTRING(NAME,1, 3)='ABC'

      应改为: WHERE NAME LIKE'ABC%'

      日期查询的例子:

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')=0

      应改为:WHERE 日期='2010-06-30' AND 日期 '2010-07-01'

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')0

      应改为:WHERE 日期 '2010-06-30'

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')=0

      应改为:WHERE 日期 '2010-07-01'

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')0

      应改为:WHERE 日期='2010-07-01'

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')=0

      应改为:WHERE 日期='2010-06-30'

      (5)不要对索引字段使用函数

      WHERE LEFT(NAME, 3)='ABC' 或者WHERE SUBSTRING(NAME,1, 3)='ABC'

      应改为: WHERE NAME LIKE 'ABC%'

      日期查询的例子:

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')=0

      应改为:WHERE 日期='2010-06-30'AND 日期 '2010-07-01'

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')0

      应改为:WHERE 日期 '2010-06-30'

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')=0

      应改为:WHERE 日期 '2010-07-01'

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')0

      应改为:WHERE 日期='2010-07-01'

      WHEREDATEDIFF(DAY, 日期,'2010-06-30')=0

      应改为:WHERE 日期='2010-06-30'

      (6)不要对索引字段进行多字段连接

      比如:

      WHERE FAME+'. '+LNAME='HAIWEI.YANG'

      应改为:

      WHERE FNAME='HAIWEI' AND LNAME='YANG'

      八:多表连接的连接条件对索引的选择有着重要的意义,所以我们在写连接条件条件的时候需要特别注意。

      A、多表连接的时候,连接条件必须写全,宁可重复,不要缺漏。

      B、连接条件尽量使用聚集索引

      C、注意ON、WHERE和HAVING部分条件的区别

      ON是最先执行, WHERE次之,HAVING最后,因为ON是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的,WHERE也应该比HAVING快点的,因为它过滤数据后才进行SUM,在两个表联接时才用ON的,所以在一个表的时候,就剩下WHERE跟HAVING比较了。

      1

      考虑联接优先顺序:

      2

      (1) INNER JOIN

      3

      (2) LEFT JOIN (注:RIGHT JOIN 用 LEFT JOIN 替代)

      4

      (3) CROSS JOIN

      其它注意和了解的地方有:

      A、在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减少判断的次数。

      B、注意UNION和UNION ALL的区别。-- 允许重复数据用UNION ALL好

      C、注意使用DISTINCT,在没有必要时不要用。

      D、TRUNCATE TABLE 与 DELETE 区别。

      E、减少访问数据库的次数。

      还有就是我们写存储过程,如果比较长的话,最后用标记符标开,因为这样可读性很好,即使语句写的不怎么样,但是语句工整,C# 有region,SQL我比较喜欢用的就是:

      --startof 查询在职人数

      SQL语句

      --end of

      正式机器上我们一般不能随便调试程序,但是很多时候程序在我们本机上没问题,但是进正式系统就有问题,但是我们又不能随便在正式机器上操作,那么怎么办呢?我们可以用回滚来调试我们的存储过程或者是SQL语句,从而排错。

      BEGINTRAN

      UPDATE a SET 字段=''

      ROLLBACK

      作业存储过程我一般会加上下面这段,这样检查错误可以放在存储过程,如果执行错误回滚操作,但是如果程序里面已经有了事务回滚,那么存储过程就不要写事务了,这样会导致事务回滚嵌套降低执行效率,但是我们很多时候可以把检查放在存储过程里,这样有利于我们解读这个存储过程,和排错。

      BEGINTRANSACTION

      --事务回滚开始

      --检查报错

      IF ( @@ERROR0 )

      BEGIN

      --回滚操作

      ROLLBACKTRANSACTION

      RAISERROR('删除工作报告错误', 16, 3)

      RETURN

      END

      --结束事务

      COMMITTRANSACTION

    bitsCN.com
    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    Video Face Swap

    Video Face Swap

    使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

    顯示更多

    熱門文章

    <🎜>:種植花園 - 完整的突變指南
    3 週前 By DDD
    <🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
    3 週前 By 尊渡假赌尊渡假赌尊渡假赌
    如何修復KB5055612無法在Windows 10中安裝?
    3 週前 By DDD
    北端:融合系統,解釋
    3 週前 By 尊渡假赌尊渡假赌尊渡假赌
    藍王子:如何到達地下室
    4 週前 By DDD
    顯示更多

    熱工具

    記事本++7.3.1

    記事本++7.3.1

    好用且免費的程式碼編輯器

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    禪工作室 13.0.1

    禪工作室 13.0.1

    強大的PHP整合開發環境

    Dreamweaver CS6

    Dreamweaver CS6

    視覺化網頁開發工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神級程式碼編輯軟體(SublimeText3)

    顯示更多

    熱門話題

    Java教學
    1664
    14
    CakePHP 教程
    1423
    52
    Laravel 教程
    1318
    25
    PHP教程
    1268
    29
    C# 教程
    1248
    24
    顯示更多
    Related knowledge
    四款值得推薦的AI輔助程式工具 四款值得推薦的AI輔助程式工具 Apr 22, 2024 pm 05:34 PM

    這個AI輔助程式工具在這個AI快速發展的階段,挖掘出了一大批好用的AI輔助程式工具。 AI輔助程式設計工具能夠提升開發效率、提升程式碼品質、降低bug率,是現代軟體開發過程中的重要助手。今天大姚給大家分享4款AI輔助程式工具(而且都支援C#語言),希望對大家有幫助。 https://github.com/YSGStudyHards/DotNetGuide1.GitHubCopilotGitHubCopilot是一款AI編碼助手,可幫助你更快、更省力地編寫程式碼,從而將更多精力集中在問題解決和協作上。 Git

    AI程式設計師哪家強?探索Devin、通靈靈碼和SWE-agent的潛力 AI程式設計師哪家強?探索Devin、通靈靈碼和SWE-agent的潛力 Apr 07, 2024 am 09:10 AM

    2022年3月3日,距離世界首個AI程式設計師Devin誕生不足一個月,普林斯頓大學的NLP團隊開發了一個開源AI程式設計師SWE-agent。它利用GPT-4模型在GitHub儲存庫中自動解決問題。 SWE-agent在SWE-bench測試集上的表現與Devin相似,平均耗時93秒,解決了12.29%的問題。 SWE-agent透過與專用終端交互,可以開啟、搜尋文件內容,使用自動語法檢查、編輯特定行,以及編寫和執行測試。 (註:以上內容為原始內容微調,但保留了原文中的關鍵訊息,未超過指定字數限制。)SWE-A

    學習如何利用Go語言開發行動應用程式 學習如何利用Go語言開發行動應用程式 Mar 28, 2024 pm 10:00 PM

    Go語言開發行動應用程式教學隨著行動應用程式市場的不斷蓬勃發展,越來越多的開發者開始探索如何利用Go語言開發行動應用程式。作為一種簡潔高效的程式語言,Go語言在行動應用開發中也展現了強大的潛力。本文將詳細介紹如何利用Go語言開發行動應用程序,並附上具體的程式碼範例,幫助讀者快速入門並開始開發自己的行動應用程式。一、準備工作在開始之前,我們需要準備好開發環境和工具。首

    五大熱門Go語言庫總表:開發必備利器 五大熱門Go語言庫總表:開發必備利器 Feb 22, 2024 pm 02:33 PM

    五大熱門Go語言庫總結:開發必備利器,需要具體程式碼範例Go語言自從誕生以來,受到了廣泛的關注和應用。作為一門新興的高效、簡潔的程式語言,Go的快速發展離不開豐富的開源程式庫的支援。本文將介紹五大熱門的Go語言庫,這些庫在Go開發中扮演了至關重要的角色,為開發者提供了強大的功能和便利的開發體驗。同時,為了更好地理解這些庫的用途和功能,我們會結合具體的程式碼範例進行講

    Android開發最適合的Linux發行版是哪一個? Android開發最適合的Linux發行版是哪一個? Mar 14, 2024 pm 12:30 PM

    Android開發是一項繁忙而又令人興奮的工作,而選擇適合的Linux發行版來進行開發則顯得尤為重要。在眾多的Linux發行版中,究竟哪一個最適合Android開發呢?本文將從幾個方面來探討這個問題,並給出具體的程式碼範例。首先,我們來看看目前流行的幾個Linux發行版:Ubuntu、Fedora、Debian、CentOS等,它們都有各自的優點和特點。

    Go語言前端技術探秘:前端開發新視野 Go語言前端技術探秘:前端開發新視野 Mar 28, 2024 pm 01:06 PM

    Go語言作為一種快速、高效的程式語言,在後端開發領域廣受歡迎。然而,很少有人將Go語言與前端開發聯繫起來。事實上,使用Go語言進行前端開發不僅可以提高效率,還能為開發者帶來全新的視野。本文將探討使用Go語言進行前端開發的可能性,並提供具體的程式碼範例,幫助讀者更了解這一領域。在傳統的前端開發中,通常會使用JavaScript、HTML和CSS來建立使用者介面

    全面指南:詳解Java虛擬機器安裝過程 全面指南:詳解Java虛擬機器安裝過程 Jan 24, 2024 am 09:02 AM

    Java開發必備:詳細解讀Java虛擬機器安裝步驟,需要具體程式碼範例隨著電腦科學和技術的發展,Java語言已成為廣泛使用的程式語言之一。它具有跨平台、物件導向等優點,逐漸成為開發人員的首選語言。在使用Java進行開發之前,首先需要安裝Java虛擬機器(JavaVirtualMachine,JVM)。本文將詳細解讀Java虛擬機器的安裝步驟,並提供具體的程式碼示

    Git 必知秘技:讓 Java 開發驚人全場 Git 必知秘技:讓 Java 開發驚人全場 Mar 06, 2024 am 08:25 AM

    1.分支與合併分支允許您在不影響主分支的情況下試驗程式碼變更。使用gitcheckout建立新分支,並在嘗試新功能或修復錯誤時使用它。完成後,使用gitmerge將變更合併回主分支。範例程式碼:gitcheckout-bnew-feature//在new-feature分支上進行更改gitcheckoutmaingitmergenew-feature2.暫存工作使用gitadd將您要追蹤的變更新增至暫存區。這使您可以選擇性地提交更改,而無需提交所有修改。範例程式碼:gitaddMyFile.java3

    See all articles

    公益線上PHP培訓,幫助PHP學習者快速成長!

    關於我們 免責聲明 Sitemap

    © php.cn All rights reserved