我们所有使用关系数据库的人都知道(或正在学习)SQL是不同的。获得期望的结果,并有效地这样做,涉及到一个乏味的过程,其部分特征是学习不熟悉的范例,并发现一些我们最熟悉的编程模式在这里不起作用。常见的反模式是什么?
当前回答
以下是我的前3名。
1号。指定字段列表失败。(编辑:为了防止混淆:这是一个生产代码规则。它不适用于一次性分析脚本——除非我是作者。)
SELECT *
Insert Into blah SELECT *
应该是
SELECT fieldlist
Insert Into blah (fieldlist) SELECT fieldlist
2号。使用游标和while循环,当while循环和循环变量就可以了。
DECLARE @LoopVar int
SET @LoopVar = (SELECT MIN(TheKey) FROM TheTable)
WHILE @LoopVar is not null
BEGIN
-- Do Stuff with current value of @LoopVar
...
--Ok, done, now get the next value
SET @LoopVar = (SELECT MIN(TheKey) FROM TheTable
WHERE @LoopVar < TheKey)
END
3号。DateLogic通过字符串类型。
--Trim the time
Convert(Convert(theDate, varchar(10), 121), datetime)
应该是
--Trim the time
DateAdd(dd, DateDiff(dd, 0, theDate), 0)
我最近看到了一个高峰“一个问题总比两个好,对吧?”
SELECT *
FROM blah
WHERE (blah.Name = @name OR @name is null)
AND (blah.Purpose = @Purpose OR @Purpose is null)
这个查询需要两个或三个不同的执行计划,具体取决于参数的值。对于这个SQL文本,只生成一个执行计划并保存在缓存中。无论参数的值是多少,都将使用该计划。这会导致间歇性的性能不佳。最好编写两个查询(每个预期的执行计划一个查询)。
其他回答
我一直对大多数程序员倾向于在数据访问层混合他们的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层紧密耦合在一起。最重要的是,这种编程风格彻底阻止了存储过程的可重用性。
Human readable password fields, egad. Self explanatory. Using LIKE against indexed columns, and I'm almost tempted to just say LIKE in general. Recycling SQL-generated PK values. Surprise nobody mentioned the god-table yet. Nothing says "organic" like 100 columns of bit flags, large strings and integers. Then there's the "I miss .ini files" pattern: storing CSVs, pipe delimited strings or other parse required data in large text fields. And for MS SQL server the use of cursors at all. There's a better way to do any given cursor task.
编辑是因为有太多了!
我最担心的是450列的访问表,这些表是由总经理最好的朋友狗美容师的8岁儿子整理的,还有那个不可靠的查找表,它之所以存在,是因为有人不知道如何正确地规范化数据结构。
通常,这个查找表是这样的:
ID INT, Name NVARCHAR(132), IntValue1 INT, IntValue2 INT, CharValue1 NVARCHAR(255), CharValue2 NVARCHAR(255), Date1 DATETIME, Date2 DATETIME
我已经记不清有多少客户的系统依赖于这种可恶的东西了。
临时表滥用。
特别是这类事情:
SELECT personid, firstname, lastname, age
INTO #tmpPeople
FROM People
WHERE lastname like 's%'
DELETE FROM #tmpPeople
WHERE firstname = 'John'
DELETE FROM #tmpPeople
WHERE firstname = 'Jon'
DELETE FROM #tmpPeople
WHERE age > 35
UPDATE People
SET firstname = 'Fred'
WHERE personid IN (SELECT personid from #tmpPeople)
不要从查询中构建临时表,只是为了删除不需要的行。
是的,我在生产db中看到过这种形式的代码页。
The Altered View - A view that is altered too often and without notice or reason. The change will either be noticed at the most inappropriate time or worse be wrong and never noticed. Maybe your application will break because someone thought of a better name for that column. As a rule views should extend the usefulness of base tables while maintaining a contract with consumers. Fix problems but don't add features or worse change behavior, for that create a new view. To mitigate do not share views with other projects and, use CTEs when platforms allow. If your shop has a DBA you probably can't change views but all your views will be outdated and or useless in that case. The !Paramed - Can a query have more than one purpose? Probably but the next person who reads it won't know until deep meditation. Even if you don't need them right now chances are you will, even if it's "just" to debug. Adding parameters lowers maintenance time and keep things DRY. If you have a where clause you should have parameters. The case for no CASE - SELECT CASE @problem WHEN 'Need to replace column A with this medium to large collection of strings hanging out in my code.' THEN 'Create a table for lookup and add to your from clause.' WHEN 'Scrubbing values in the result set based on some business rules.' THEN 'Fix the data in the database' WHEN 'Formating dates or numbers.' THEN 'Apply formating in the presentation layer.' WHEN 'Createing a cross tab' THEN 'Good, but in reporting you should probably be using cross tab, matrix or pivot templates' ELSE 'You probably found another case for no CASE but now I have to edit my code instead of enriching the data...' END
推荐文章
- 如何在SQL中选择表的最后一条记录?
- SQL在Oracle中连接多行列值的查询
- 在单个查询中计算空值和非空值
- 在存储过程中使用“SET XACT_ABORT ON”有什么好处?
- SQL to LINQ工具
- 如何从一个查询插入多行使用雄辩/流利
- 如何连接列在Postgres选择?
- 有人可以对SQL查询进行版权保护吗?
- 如何知道MySQL表最近一次更新?
- 如何转储一些SQLite3表的数据?
- 如何创建一个SQL Server函数“连接”多行从一个子查询到一个单独的分隔字段?
- 在MySQL中的一个查询中更新多个具有不同值的行
- 在SQL中更新多个列
- 如何删除表中特定列的第一个字符?
- MySQL OR与IN性能