【发布时间】:2008-12-06 19:42:15
【问题描述】:
我们所有使用关系数据库的人都知道(或正在学习)SQL 是不同的。引出所需的结果并有效地完成这一过程涉及一个乏味的过程,其部分特征是学习不熟悉的范例,并发现我们最熟悉的一些编程模式在这里不起作用。您见过(或您自己承诺过)的常见反模式有哪些?
【问题讨论】:
标签: sql anti-patterns
我们所有使用关系数据库的人都知道(或正在学习)SQL 是不同的。引出所需的结果并有效地完成这一过程涉及一个乏味的过程,其部分特征是学习不熟悉的范例,并发现我们最熟悉的一些编程模式在这里不起作用。您见过(或您自己承诺过)的常见反模式有哪些?
【问题讨论】:
标签: sql anti-patterns
我刚刚遇到这样的视图定义:
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 列。一些开发人员以不提供列别名来折磨他人而感到自豪,因此必须计算这两个位置的列偏移量,以便能够确定视图中的列对应。
【讨论】:
我见过太多的人为了生命而坚持IN (...),而完全忘记了EXISTS。有关一个很好的示例,请参阅 Symfony Propel ORM。
【讨论】:
应用程序连接 不仅仅是一个 SQL 问题,而是寻找问题的描述并找到这个问题,我很惊讶它没有被列出。
正如我听说的那样,应用程序连接是指从两个或多个表中的每一个中提取一组行,然后使用一对嵌套的 for 循环将它们连接到 (Java) 代码中。这使系统(您的应用程序和数据库)不得不识别整个交叉产品,检索它并将其发送到应用程序。假设应用程序可以像数据库一样快地过滤叉积(可疑),只是更快地减少结果集意味着更少的数据传输。
【讨论】:
将冗余表加入到这样的查询中:
select emp.empno, dept.deptno
from emp
join dept on dept.deptno = emp.deptno;
【讨论】:
dept 行存在,它只返回emp 行。
SELECT 子句中使用emp.deptno(而不是dept.deptno)可能会更好,使用SELECT DISTINCT(而不是SELECT ALL)更好。但也许最好使用更明显是半连接的东西,例如SELECT empno, deptn FROM emp WHERE EXISTS (SELECT * FROM dept WHERE dept.deptno = emp.deptno);
有 1 张桌子
code_1
value_1
code_2
value_2
...
code_10
value_10
而不是3张桌子
代码、值和代码值
你永远不知道什么时候你可能需要超过 10 对情侣代码,价值。
如果您只需要一对,就不会浪费磁盘空间。
【讨论】:
code_value 表?不就是数据重复吗?
re:使用@@IDENTITY 代替 SCOPE_IDENTITY()
你都不应该使用;改用输出
【讨论】:
我最喜欢的 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;
【讨论】:
也许不是一种反模式,但让我烦恼的是某些 DB 的 DBA(好吧,我在这里谈论的是 Oracle)使用 Oracle 样式和代码约定编写 SQL Server 代码并在运行如此糟糕时抱怨。 Oracle 人用光标就够了! SQL 是基于设置的。
【讨论】:
不使用 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'
)
【讨论】: