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


当前回答

没有注释的存储过程或函数…

其他回答

不必深入浅出:不使用准备好的语句。

我见过太多人死死抓着IN(…),却完全忘记了EXISTS(存在)。有关一个好例子,请参见Symfony Propel ORM。

我一直对大多数程序员倾向于在数据访问层混合他们的ui逻辑感到失望:

SELECT
    FirstName + ' ' + LastName as "Full Name",
    case UserRole
        when 2 then "Admin"
        when 1 then "Moderator"
        else "User"
    end as "User's Role",
    case SignedIn
        when 0 then "Logged in"
        else "Logged out"
    end as "User signed in?",
    Convert(varchar(100), LastSignOn, 101) as "Last Sign On",
    DateDiff('d', LastSignOn, getDate()) as "Days since last sign on",
    AddrLine1 + ' ' + AddrLine2 + ' ' + AddrLine3 + ' ' +
        City + ', ' + State + ' ' + Zip as "Address",
    'XXX-XX-' + Substring(
        Convert(varchar(9), SSN), 6, 4) as "Social Security #"
FROM Users

通常,程序员这样做是因为他们想要将数据集直接绑定到一个网格上,而且在服务器端使用SQL Server格式比在客户端使用SQL Server格式更方便。

像上面所示的查询是非常脆弱的,因为它们将数据层与UI层紧密耦合在一起。最重要的是,这种编程风格彻底阻止了存储过程的可重用性。

我最喜欢的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;

重新使用一个“死”字段来做一些它不打算做的事情(例如在“传真”字段中存储用户数据)-尽管作为一个快速修复非常诱人!