是否应在SQL语句中指定日期格式?


8

我看到开发人员使用隐式日期转换的代码。对于他们为什么不应该这样做,我想要一个明确的答案。

SELECT * from dba_objects WHERE Created >= '06-MAR-2012';

1
你有一些例子吗?
FrustratedWithFormsDesigner 2012年

1
@Frustrated添加了一个示例。
Leigh Riffel'3

我什至会走得那么远,除非您在to_date()调用中也使用了NLS_DATE_LANGUAGE参数,否则您也不应使用缩写的月份名称
a_horse_with_no_name 2012年

Answers:


15

因为'2012/12/1'在美国,在欧洲相同的字符串日期之后是11个月。

允许隐式转换意味着您受位置设置的支配。

如果您可以命名一个可接受的误差范围为11个月的企业,那么我会留下深刻的印象。


6
确实,“ 01/01/11”可能要等10年。+1
Leigh Riffel 2012年

@LeighRiffel:甚至110年关闭...
ypercubeᵀᴹ

+1,永远不要依赖隐式DATE转换(或任何隐式数据类型转换)
a_horse_with_no_name 2012年

2
“给企业指定11个月的误差范围是可以接受的” –族谱引擎在搜索注册时倾向于在输入年份的任一侧留两年。
某天,2012年

1
@onedaywhen好答案-如前所述,我印象深刻!
JNK 2012年

14

如果具有不同日期格式的会话运行该代码,则会出现问题。

陈述失败

DROP TABLE t1;
CREATE TABLE t1 AS (SELECT sysdate mydate FROM dual WHERE 1=2);
ALTER SESSION SET NLS_DATE_FORMAT = 'MON-DD-RR';
INSERT INTO t1 VALUES ('01-02-12');
                       *
ERROR at line 1:
ORA-01843: not a valid month

不良数据

  DROP TABLE t1;
  CREATE TABLE t1 AS (SELECT sysdate mydate FROM dual WHERE 1=2);

  --User 1
  ALTER SESSION SET NLS_DATE_FORMAT = 'MM-DD-RR';
  INSERT INTO t1 VALUES ('01-02-11');

  --User 2
  ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MM-RR';
  INSERT INTO t1 VALUES ('01-02-11');

  --User 3
  ALTER SESSION SET NLS_DATE_FORMAT = 'RR-MM-DD';
  INSERT INTO t1 VALUES ('01-02-11');

  SELECT to_char(mydate,'MM/DD/YYYY') FROM t1;

在这种情况下,因为每个alter / insert语句可以由不同的用户完成。它们都将运行相同的语句,但是结果日期将完全不同。插入语句可能埋在仅被间接调用的包中。由于未返回任何错误,因此可能要等到很久以后才能发现问题。

SQL注入

  CLEAR SCREEN;
  DROP TABLE Secrets;
  CREATE TABLE Secrets (RevealDate Date, Secret Varchar2(200));
  INSERT INTO Secrets VALUES (trunc(sysdate),   '*** Common Knowledge. ***');
  INSERT INTO Secrets VALUES (trunc(sysdate+1), '*** Don''t Let Anyone know this. ***');

  CREATE OR REPLACE PROCEDURE ShowRevealedSecrets IS
     vStatement varchar2(200);
     vOutput Varchar2(1000);
     vDate date:=sysdate;
  begin
  vStatement:='SELECT secret FROM Secrets WHERE RevealDate = ''' || vDate || '''';
  execute immediate vStatement INTO vOutput;
  DBMS_Output.Put_Line(vOutput);
  END;
  /

  --Normal Use.     
  ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YY';
  EXEC ShowRevealedSecrets();

  --Explointing SQL Injection
  ALTER SESSION SET NLS_DATE_FORMAT = '"'' OR RevealDate > sysdate--"';
  EXEC ShowRevealedSecrets();

在这种情况下,恶意个人可能会以某种方式更改会话日期格式,以使他们能够访问通常不会访问的数据。


+1,但我认为SQL注入情况非常狭窄。
JNK 2012年

1
@JNK我同意,这使得它更有可能在代码审查中丢失。
Leigh Riffel 2012年

1
题外话,但这个SQL注入白皮书是辉煌的:accuvant.com/capability/accuvant-labs/security-research/...
Philᵀᴹ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.