我花了很多时间在SO上回答SQL问题。我经常遇到这样的问题:
SELECT * FROM person WHERE birthdate BETWEEN '01/01/2017' AND '01/03/2017'
SELECT * FROM person WHERE birthdate BETWEEN '2017-01-01' AND '2017-03-01'
SELECT * FROM person WHERE birthdate BETWEEN 'some string' AND 'other string'
即要么依赖给定参数从字符串到日期的隐式转换(错误),要么依赖数据库将x百万个数据库行值转换为字符串并进行字符串比较(更糟糕)
我偶尔会发表评论,尤其是如果这是一个非常有名的用户,他们编写了一个明智的答案,但是我认为,他们的数据类型确实应该少一些草率/字符串式输入
注释通常采用以下形式:如果他们使用to_date(Oracle),str_to_date(MySQL),convert(SQLSERVER)或类似的机制将字符串显式转换为日期,可能会更好:
--oracle
SELECT * FROM person WHERE birthdate BETWEEN TO_DATE('20170101', 'YYYYMMDD') AND TO_DATE('20170301', 'YYYYMMDD')
--mysql
SELECT * FROM person WHERE birthdate BETWEEN STR_TO_DATE('20170101', '%Y%m%d') AND STR_TO_DATE('20170301', '%Y%m%d')
--SQLS, ugh; magic numbers
SELECT * FROM person WHERE birthdate BETWEEN CONVERT(datetime, '20170101', 112) AND CONVERT(datetime, '20170301', 112)
我这样做的技术理由是,它对日期的格式是明确的,并确保少数几个源参数确实成为目标列的数据类型。这样可以避免数据库错误地进行隐式转换(第一个示例的3rd Jan / 1st Mar参数),并且可以防止db决定将表中的一百万个日期值转换为字符串(使用某些服务器特定的日期)格式可能甚至与sql中的字符串参数中的日期格式都不匹配)以进行比较-恐怖比比皆是
我这样做的社会/学术理由是SO是一个学习网站;人们从中隐性或显性地获取知识。要使用此查询作为答案来打新手:
SELECT * FROM person WHERE birthdate BETWEEN '2017-01-01' AND '2017-03-01'
可能会导致他们认为这很明智,并根据他们喜欢的某种格式调整日期:
SELECT * FROM person WHERE birthdate BETWEEN '01/01/2017' AND '01/03/2017'
如果他们至少看到了一些明确的尝试来转换日期,他们可能会以其怪异的日期格式开始执行此操作,并在它们出现之前将其永久杀死。毕竟,我们(I)试图阻止人们养成SQL注入习惯(@pBirthdate
当前端具有datetime类型时,有人会提倡参数化查询,然后向驱动程序声明字符串吗?)
回到我提出建议后会发生的情况:我通常会对“明确使用x”建议有所反驳,例如“其他人都这样做”,“它总是对我有用”,“向我展示一些手册或参考文档”那说我应该是露骨的”甚至“是什么?”
针对这些问题,我问他们是否WHERE age = '99'
通过将年龄作为字符串传递来搜索int列。回答是:“别傻,我们在搜索int时不需要放',因此他们对某些数据类型的想法有所了解,但也许与搜索int的逻辑飞跃无关通过传递字符串(显然是愚蠢的)并通过传递字符串(显然是明智的)来搜索日期列是虚伪的
因此,在我们的SQL中,我们有一种方法可以将内容写为数字(使用数字,不带分隔符),将内容写为字符串(在撇号分隔符之间使用任何东西)。为什么没有日期分隔符?在大多数数据库中,这是基本数据类型吗?是否可以通过以与javascript让我们通过在/
某些字符的任意一侧指定正则表达式相同的方式编写日期来解决整个问题。/Hello\s+world/
。为什么没有约会用的东西?
实际上,据我所知,(仅)Microsoft Access实际上具有指示“在这些定界符之间已写有日期的符号”,因此我们可以得到一个很好的快捷方式,例如WHERE datecolumn = #somedate#
,日期显示仍然容易出现问题,例如mm / di vs dd / mm,因为MS总是在VB人群认为是个好主意的东西上玩得很快而松散
回到主要要点:我认为使用这种媒介是明确的,这迫使我们将许多不同的数据类型作为字符串进行传递是明智的。
这是有效的断言吗?
我应该继续进行这次讨伐吗?字符串输入是现代的禁忌法是否有效?还是在推销查询时WHERE datecolumn = 'string value'
绝对肯定地将每个RDBMS(包括古代版本)正确地将字符串转换为日期,并且在不转换表数据/不使用索引的情况下进行搜索?我怀疑不是这样,至少从Oracle 9的个人经验来看,我也怀疑如果字符串始终以某种ISO标准格式编写,并且该列具有某种日期风味,那么可能会有一些逃脱的情况。字符串参数将始终正确地隐式转换。这样对吗?
这是一项值得的任务吗?
许多人似乎不了解,不在乎或表现出一些虚伪,因为他们的整数是整数,但日期是字符串。.尽管大多数人的共同之处是很少有人转过身说:“你知道什么,我同意你的观点。从现在开始,我将明确说明我的约会。”
WHERE age = '0x0F'
是希望数据库将搜索十五岁的一个有效方式..
WHERE datecolumn =
01/02 / 12'`上遇到问题,有可能他们要求的年份是1912、2012、2001、1901、12或1。这也是数据库世界之外的一个问题,数字无法理解为什么转换"09"
为int会导致崩溃的程序员中,有9个不是有效的八进制数字,而前导0使字符串在许多系统中都是八进制的