【问题标题】:What are the most common SQL anti-patterns? [closed]最常见的 SQL 反模式有哪些? [关闭]
【发布时间】:2008-12-06 19:42:15
【问题描述】:

我们所有使用关系数据库的人都知道(或正在学习)SQL 是不同的。引出所需的结果并有效地完成这一过程涉及一个乏味的过程,其部分特征是学习不熟悉的范例,并发现我们最熟悉的一些编程模式在这里不起作用。您见过(或您自己承诺过)的常见反模式有哪些?

【问题讨论】:

标签: sql anti-patterns


【解决方案1】:

我刚刚遇到这样的视图定义:

CREATE OR REPLACE FORCE VIEW PRICE (PART_NUMBER, PRICE_LIST, LIST_VERSION ...)
AS
  SELECT sp.MKT_PART_NUMBER,
    sp.PRICE_LIST,
    sp.LIST_VERSION,
    sp.MIN_PRICE,
    sp.UNIT_PRICE,
    sp.MAX_PRICE,
...

视图中有大约 50 列。一些开发人员以不提供列别名来折磨他人而感到自豪,因此必须计算这两个位置的列偏移量,以便能够确定视图中的列对应。

【讨论】:

    【解决方案2】:

    我见过太多的人为了生命而坚持IN (...),而完全忘记了EXISTS。有关一个很好的示例,请参阅 Symfony Propel ORM。

    【讨论】:

      【解决方案3】:

      应用程序连接 不仅仅是一个 SQL 问题,而是寻找问题的描述并找到这个问题,我很惊讶它没有被列出。

      正如我听说的那样,应用程序连接是指从两个或多个表中的每一个中提取一组行,然后使用一对嵌套的 for 循环将它们连接到 (Java) 代码中。这使系统(您的应用程序和数据库)不得不识别整个交叉产品,检索它并将其发送到应用程序。假设应用程序可以像数据库一样快地过滤叉积(可疑),只是更快地减少结果集意味着更少的数据传输。

      【讨论】:

        【解决方案4】:

        将冗余表加入到这样的查询中:

        select emp.empno, dept.deptno
        from emp
        join dept on dept.deptno = emp.deptno;
        

        【讨论】:

        • 这实际上做了一些事情:如果相应的dept 行存在,它只返回emp 行。
        • @Ariel:关键是,它是一个semi-join,但这一事实并没有立即显现。在SELECT 子句中使用emp.deptno(而不是dept.deptno)可能会更好,使用SELECT DISTINCT(而不是SELECT ALL)更好。但也许最好使用更明显是半连接的东西,例如SELECT empno, deptn FROM emp WHERE EXISTS (SELECT * FROM dept WHERE dept.deptno = emp.deptno);
        【解决方案5】:

        有 1 张桌子

        code_1
        value_1
        code_2
        value_2
        ...
        code_10
        value_10
        

        而不是3张桌子

        代码、值和代码值

        你永远不知道什么时候你可能需要超过 10 对情侣代码,价值。

        如果您只需要一对,就不会浪费磁盘空间。

        【讨论】:

        • 我不明白你为什么需要code_value 表?不就是数据重复吗?
        【解决方案6】:

        re:使用@@IDENTITY 代替 SCOPE_IDENTITY()

        你都不应该使用;改用输出

        参见。 https://connect.microsoft.com/SQLServer/feedback/details/328811/scope-identity-sometimes-returns-incorrect-value

        【讨论】:

        • 链接已损坏。最好包含相关文本而不是包含链接
        【解决方案7】:

        我最喜欢的 SQL 反模式:

        JOIN 在非唯一列上并使用SELECT DISTINCT 修剪结果。

        创建一个连接多个表的视图,只是为了从一个表中选择几列。

         CREATE VIEW my_view AS 
             SELECT * FROM table1
             JOIN table2 ON (...)
             JOIN table3 ON (...);
        
         SELECT col1, col2 FROM my_view WHERE col3 = 123;
        

        【讨论】:

          【解决方案8】:

          也许不是一种反模式,但让我烦恼的是某些 DB 的 DBA(好吧,我在这里谈论的是 Oracle)使用 Oracle 样式和代码约定编写 SQL Server 代码并在运行如此糟糕时抱怨。 Oracle 人用光标就够了! SQL 是基于设置的。

          【讨论】:

          • 我认为这与您的 DBA 的关系比与 Oracle 的关系更大。 Oracle 建议人们也应该基于集合来思考和行动,而不是使用游标进行逐行程序化思考。
          • 你可能是对的。但是我们公司有很多 DBA,他们似乎都喜欢游标。
          • 那么他们不是很好的DBA......你不会和我在同一个地方工作吧? ;)
          【解决方案9】:

          不使用 With 子句或适当的连接并依赖子查询。

          反模式:

          select 
           ...
          from data
          where RECORD.STATE IN (
                    SELECT STATEID
                      FROM STATE
                     WHERE NAME IN
                              ('Published to test',
                               'Approved for public',
                               'Published to public',
                               'Archived'
                              ))
          

          更好:
          我喜欢使用 with 子句使我的意图更具可读性。

          with valid_states as (
                    SELECT STATEID
                      FROM STATE
                     WHERE NAME IN
                              ('Published to test',
                               'Approved for public',
                               'Published to public',
                               'Archived'
                              )
          select  ... from data, valid_states
          where data.state = valid_states.state
          

          最佳:

          select 
            ... 
          from data join states using (state)
          where 
          states.state in  ('Published to test',
                               'Approved for public',
                               'Published to public',
                               'Archived'
                              )
          

          【讨论】:

          • 为什么?能否请您描述一下幕后的区别
          • 通常称为 CTE 或公用表表达式,必须有比这更好的示例,因为您的反模式和最佳示例更相似,并且您的论点是模式应该更好跨度>
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-26
          • 1970-01-01
          • 2010-10-04
          • 1970-01-01
          • 1970-01-01
          • 2010-10-19
          相关资源
          最近更新 更多