`
sdfiyon
  • 浏览: 21510 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

动态SQL对日期处理要特别注意

阅读更多

如果一定要是动态SQL,一定要将日期类型用||拼起来,见下列写法,红色的是错的,下面的才对,两次类型转换,但是没有什么必要

--要么用绑定变量绑定date类型,要么静态sql,不要两次转换,直接拼日期前后不加单引号还会报错。

SQL> DECLARE

  2   v_date date := sysdate;

  3   v_cnt number := 0;

  4   v_sql varchar2(100);

  5  BEGIN

  6    v_sql := 'SELECT COUNT(*) FROM USER_OBJECTS WHERE CREATED<='||v_date;  

   7    DBMS_OUTPUT.PUT_LINE(v_sql);

  8    v_sql := 'SELECT COUNT(*) FROM USER_OBJECTS WHERE CREATED<='||chr(39)||v_date||chr(39);

  9      DBMS_OUTPUT.PUT_LINE(v_sql);

10    EXECUTE IMMEDIATE v_sql INTO v_cnt;

11        DBMS_OUTPUT.PUT_LINE(v_cnt);

-- v_sql := 'SELECT COUNT(*) FROM USER_OBJECTS WHERE CREATED<=TO_DATE('''||v_date||''',''dd-mon-yy'')';

  --   DBMS_OUTPUT.PUT_LINE(v_sql);

12  END;

13  /

 

SELECT COUNT(*) FROM USER_OBJECTS WHERE CREATED<=04-1月 -11

SELECT COUNT(*) FROM USER_OBJECTS WHERE CREATED<='04-1月 -11'

1810

 

PL/SQL procedure successfully completed

 

 

 

DROP TABLE t;

CREATE TABLE t(p1 DATE)

PARTITION BY RANGE(p1)

(PARTITION p0 VALUES LESS THAN  ( TO_DATE ('20110816', 'YYYYMMDD'))  TABLESPACE USERS);

 

所以:

1.对非DDL,应该要使用绑定变量,如果绑定变量适合的话

2.DDL,用不了绑定变量,必须to_date拼凑

 

DECLARE

   p1   DATE := TO_DATE ('20110817', 'YYYYMMDD');

BEGIN

  EXECUTE IMMEDIATE 'alter session set nls_date_format=''yyyymmdd''';

   FOR i IN 1 .. 2

   LOOP

      EXECUTE IMMEDIATE

            'alter table t add partition p'

         || TO_CHAR (p1, 'YYYYMMDD')

         || '  VALUES LESS THAN ( TO_DATE('''

         || p1

         || ''',''yyyymmdd''))  TABLESPACE USERS';

 

      p1 := p1 + 1;

   END LOOP;

END;

/

 

--不用设nls_date_format,因为两次转换的nls_date_format一样,直接to_date,因为自动转换的字符串没有引号,需要补上引号

DECLARE

   p1   DATE := TO_DATE ('20110817', 'YYYYMMDD');

BEGIN

   FOR i IN 1 .. 2

   LOOP

      EXECUTE IMMEDIATE

            'alter table t add partition p'

         || TO_CHAR (p1, 'YYYYMMDD')

         || '  VALUES LESS THAN ( TO_DATE('''

         || p1

         || '''))  TABLESPACE USERS';

 

      p1 := p1 + 1;

   END LOOP;

END;

/

 

 

--甚至可以去掉to_date,自动转为目标类型,但是要补引号

 

DECLARE

   p1   DATE := TO_DATE ('20110817', 'YYYYMMDD');

BEGIN

   DBMS_OUTPUT.put_line(     'alter table t add partition p'

         || TO_CHAR (p1, 'YYYYMMDD')

         || '  VALUES LESS THAN ( '''

         || p1

         || ''')  TABLESPACE USERS');

END;

/

 

 

也可以对p使用显示转为字符串,和上面一样

  'alter table t add partition p'

         || TO_CHAR (p1, 'YYYYMMDD')

         || '  VALUES LESS THAN ( TO_DATE('''

         || TO_CHAR(p1,'YYYY-MM-DD')

         || ''',''YYYY-MM-DD''))  TABLESPACE USERS'

 

 

再看一个典型的拼凑日期的错误。

我常常看到别人不使用绑定变量,采用拼凑的方式传入日期类型,比如:

 

declare

  vname varchar2(10):='dd';

  v_sql varchar2(4000);

  vcnt number;

  v_date date:=sysdate;

begin

    v_sql:='select count(*) from test where birth='||v_date; --这里要出错

    dbms_output.put_line(v_sql);

    execute immediate v_sql into vcnt;

    dbms_output.put_line(vcnt);

end;

 

这里又出什么错呢?请看打印出的语句是什么?

select count(*) from test where birth=08-5月 -10

原来在运行期,如果采用||date,那么日期自动根据session日期设置参数转换为字符串,而字符串连接不自动加引号,所以就变成上面的了,丢失了引号,自动转换也失效,语句错误了,如果你非要那样做,只能

 

1.        将v_date转为字符串,带引号的,然后让其自动转换,如:  v_sql:='select count(*) from test where birth='''||v_date||'''';  当然也可以使用to_date,如

  v_sql:='select count(*) from test where birth=to_date('''||v_date||''')';

不需要nls_date_format设置,因为两次转换的格式一样.

也可以显示转换,代替oracle自动转换v_sql:='select count(*) from test where birth='''||to_char(v_date)||'''';

 

最完整的全部显示转换

v_sql:='select count(*) from test where birth=to_date('''||to_char(v_date,'yyyymmdd')||''',''yyyymmdd'')';

 

2.        DDL用不了绑定变量,只能使用1的方法,对非DDL,要用绑定变量,解决这个问题,一般起到软解析效果。

        以上是典型的拼凑导致的程序难以编写而且容易出错的例子,如果采用绑定变量的方式,以上问题全可迎刃而解。

 

也说明了一点,绑定变量不光使我们的SQL反复执行的效率更高,在存储过程的动态SQL里,绑定变量也会使我们减少错误的发生,更容易地进行编程(存储过程的静态SQL自动绑定,达到软解析或软软解析的效果,当然动态SQL也可能软或软软解析)

 

不加to_date,发生2次转换

第1次,v_date是date类型,但是用||运算,变为字符串

第2次,||两边加了引号,但是birth是date类型,又把字符串转为date类型

因为这两次转换的格式和环境都一样的,所以可以自动转来转去,当然可读性不是很好

分享到:
评论

相关推荐

    PL/SQL Developer8.04官网程序_keygen_汉化

     该完善器允许您通过用户定义的规则对SQL和PL/SQL代码进行规范化处理。在编译、保存、打开一个文件时,代码将自动被规范化。该特性提高了您编码的生产力,改善了PL/SQL代码的可读性,促进了大规模工作团队的协作。 ...

    SQL语法大全

    COUNT(*|字段名) 对数据行数的统计或对某一栏有值的数据行数统计 MAX(字段名) 取得一个表格栏最大的值 MIN(字段名) 取得一个表格栏最小的值 SUM(字段名) 把数据栏的值相加 引用以上函数的方法: sql="select sum...

    PLSQLDeveloper下载

    PL/SQL完善器——该完善器允许您通过用户定义的规则对SQL和PL/SQL代码进行规范化处理。在编译、保存、打开一个文件时,代码将自动被规范化。该特性提高了您编码的生产力,改善了PL/SQL代码的可读性,促进了大规模...

    orcale常用命令

    9、查看数据库的创建日期和归档方式 Select Created, Log_Mode, Log_Mode From V$Database; 四、ORACLE用户连接的管理 用系统管理员,查看当前数据库有几个用户连接: SQL&gt; select username,sid,serial# from v$...

    MySQL中文参考手册

    o 4.16 升级和降级(downgrading)时有什么特别要做的事情吗? + 4.16.1 从一个 3.22 版本升级到 3.23 + 4.16.2 从一个 3.21 版本升级到 3.22 + 4.16.3 从一个 3.20 版本升级到 3.21 + 4.16.4 升级到其他的...

    MYSQL

    4.16 升级和降级(downgrading)时有什么特别要做的事情吗? 4.16.1 从一个 3.22 版本升级到 3.23 4.16.2 从一个 3.21 版本升级到 3.22 4.16.3 从一个 3.20 版本升级到 3.21 4.16.4 升级到其他的...

    MySQL中文参考手册.chm

    MySQL 4.15.4 选项文件 4.16 升级和降级(downgrading)时有什么特别要做的事情吗? 4.16.1 从一个 3.22 版本升级到 3.23 4.16.2 从一个 3.21 版本升级到 3.22 4.16.3 从一个 3.20 版本升级到...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

     数据查询语言 (Data Query Language, DQL) 是SQL语言中,负责进行数据查询而不会对数据本身进行修改的语句,这是最基本的SQL语句。例如:SELECT(查询)  数据控制语言Data Controlling Language(DCL),用来...

    数据清洗数据分析数据挖掘.docx

    数据清洗需要注意的是不要将有用的数据过滤掉,对于每个过滤规则认真进行验证,并要用户确认。 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息和形成结论而对数据加以详细研究和概括...

    大数据:数据清洗、数据分析、数据挖掘.doc

    数据清洗需要注意的是 不要将有用的数据过滤掉,对于每个过滤规则认真进行验证,并要用户确认。 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息 和形成结论而对数据加以详细研究和概括...

    数据清洗、数据分析、数据挖掘.docx

    数据清洗需要注意的是不要将有用的数据过滤掉,对于每个过滤规则认真进行验证,并要用户确认。 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息和形成结论而对数据加以详细研究和概括...

    数据清洗-数据分析-数据挖掘.docx

    数据清洗需要注意的是不要将有用的数据过滤掉,对于每个过滤规则认真进行验证,并要用户确认。 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息和形成结论而对数据加以详细研究和概括...

    iWeb Office2000[EXE版]

    DBstep.SQL 为SQL Server备份文件,如要安装本实例,请在SQL服务器上建立DBDemo数据库 同时,建立dbdemo用户名和dbdemo密码,然后将DBstep.SQL恢复到SQL服务器上即可. ============================================...

    iWeb Office2000[OCX版]

    DBstep.SQL 为SQL Server备份文件,如要安装本实例,请在SQL服务器上建立DBDemo数据库 同时,建立dbdemo用户名和dbdemo密码,然后将DBstep.SQL恢复到SQL服务器上即可. ============================================...

    iWeb Office2000[ASP版]

    DBstep.SQL 为SQL Server备份文件,如要安装本实例,请在SQL服务器上建立DBDemo数据库 同时,建立dbdemo用户名和dbdemo密码,然后将DBstep.SQL恢复到SQL服务器上即可. ============================================...

    iWeb Office2000[C#版]

    DBstep.SQL 为SQL Server备份文件,如要安装本实例,请在SQL服务器上建立DBDemo数据库 同时,建立dbdemo用户名和dbdemo密码,然后将DBstep.SQL恢复到SQL服务器上即可. ============================================...

    iWeb Office2000[.NET版]

    DBstep.SQL 为SQL Server备份文件,如要安装本实例,请在SQL服务器上建立DBDemo数据库 同时,建立dbdemo用户名和dbdemo密码,然后将DBstep.SQL恢复到SQL服务器上即可. ============================================...

    oracle详解

    oracle会避开sql语句处理引擎,直接从数据库文件中读取数据,然后写入导出文件. 可以在导出日志中观察到: exp-00067: table xxx will be exported in conventional path 如果没有使用直接路径,必须保证buffer参数的值...

    mysql数据库的基本操作语法

    --日期 uBirthday datetime ); 8、 子查询建表方法 部分列名匹配模式: create table userInfo ( name varchar(20), sex char ) as select name, sex from user; 上面的列名和子查询的列名以及类型要对应 全部...

    易语言程序免安装版下载

    注意:静态编译后的易语言EXE和DLL之间不能再共享“某些”句柄或资源,这一点和原动态连接时的程序行为不能保持一致,使用时请务必设法避免此类用法(MYSQL支持库我们作了特别处理)。 注意:静态编译后常量数据...

Global site tag (gtag.js) - Google Analytics