我们所有使用关系数据库的人都知道(或正在学习)SQL是不同的。获得期望的结果,并有效地这样做,涉及到一个乏味的过程,其部分特征是学习不熟悉的范例,并发现一些我们最熟悉的编程模式在这里不起作用。常见的反模式是什么?


当前回答

使用无意义的表别名:

from employee t1,
department t2,
job t3,
...

使得阅读一个大的SQL语句比它需要的要困难得多

其他回答

有一张桌子

code_1
value_1
code_2
value_2
...
code_10
value_10

而不是有3个表

Code, value和code_value

你永远不知道什么时候你可能需要10对以上的代码,价值。

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

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

正如我所听到的那样,应用程序连接是指从两个或多个表中取出一组行,然后用一对嵌套的for循环将它们连接到(Java)代码中。这给系统(应用程序和数据库)带来了负担,必须识别整个叉乘,检索它并将其发送给应用程序。假设应用程序可以像数据库一样快地过滤叉乘(不确定),只是更快地削减结果集意味着更少的数据传输。

回复:使用@@IDENTITY代替SCOPE_IDENTITY()

两者都不能用;使用输出代替

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

同一查询中的相同子查询。

使用SQL作为美化的ISAM(索引顺序访问方法)包。特别是嵌套游标,而不是将SQL语句组合成一个更大的语句。这也算“滥用优化器”,因为实际上优化器能做的不多。这可以与非准备语句结合使用,以获得最大的效率:

DECLARE c1 CURSOR FOR SELECT Col1, Col2, Col3 FROM Table1

FOREACH c1 INTO a.col1, a.col2, a.col3
    DECLARE c2 CURSOR FOR
        SELECT Item1, Item2, Item3
            FROM Table2
            WHERE Table2.Item1 = a.col2
    FOREACH c2 INTO b.item1, b.item2, b.item3
        ...process data from records a and b...
    END FOREACH
END FOREACH

正确的解决方案(几乎总是)是将两个SELECT语句合并为一个:

DECLARE c1 CURSOR FOR
    SELECT Col1, Col2, Col3, Item1, Item2, Item3
        FROM Table1, Table2
        WHERE Table2.Item1 = Table1.Col2
        -- ORDER BY Table1.Col1, Table2.Item1

FOREACH c1 INTO a.col1, a.col2, a.col3, b.item1, b.item2, b.item3
    ...process data from records a and b...
END FOREACH

双循环版本的唯一优点是,您可以很容易地发现表1中值之间的中断,因为内部循环结束了。这可能是控制中断报告中的一个因素。

此外,应用程序中的排序通常是不允许的。