`
sdfiyon
  • 浏览: 22204 次
  • 性别: 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类型

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

分享到:
评论

相关推荐

    SQL动态日期列生成并统计

    在SQL中,动态生成日期列是一项常见的需求,特别是在数据分析和报表生成时。这个场景中,我们需要根据输入的日期区间,比如"2015-08"到"2016-02",生成相应的日期列,并进行统计。下面我们将深入探讨如何实现这一...

    SQL Server中日期问题的解决

    ### SQL Server中日期问题的解决 在Microsoft SQL Server(以下简称SQL Server)中处理日期和时间时,经常会...此外,随着SQL Server版本的不断更新,还会有更多的新特性被引入,以支持更加灵活和强大的日期处理功能。

    SQL Server 查询两个日期之间的所有月份

    首先,我们需要理解SQL Server中的日期处理函数。`DATEADD`函数允许我们向或从日期添加指定的时间间隔,例如月份。`MONTH`函数则用于提取日期中的月份部分。在给定的代码示例中,`@min`和`@max`分别存储了起始和结束...

    SQL日期的方法及例子

    总之,掌握SQL中的日期处理技巧对于任何数据库开发者来说都至关重要,因为它们提供了对日期数据的强大操作能力,使你能够构建出复杂且精确的查询逻辑。理解并熟练使用这些函数,将有助于提升你的SQL编程技能,并优化...

    sql中的按日期统计问题

    在SQL(结构化查询语言)中,处理按日期统计的问题是一项常见的任务,特别是在数据分析、报表生成和业务智能领域。这类问题通常涉及到从数据库中提取特定日期范围内的数据,或者计算不同日期区间的数据量。以下是对...

    DB2 日期数据库的sql语句

    ### DB2数据库中获取当前日期与时间的相关SQL语句 在DB2数据库系统中,处理日期和时间数据是一项常见的需求。对于开发人员来说,能够准确地获取和操作日期时间数据至关重要。本文将详细介绍如何在DB2数据库中使用...

    SQL日期和时间函数.txt sql

    ### SQL日期和时间函数解析与应用 在数据库管理和数据分析领域,正确处理...通过掌握并灵活运用这些SQL日期和时间函数,可以显著提升数据处理的效率和准确性,特别是在涉及到历史数据的分析和实时数据的监控场景下。

    SQL Server数据库提交日期的动态实现.pdf

    本文将介绍如何利用Dreamweaver的Extension扩展程序,实现向SQL Server 2000数据库动态提交日期数据的过程。 首先,需要明确动态网页中提交日期到数据库的一般方法。传统上,开发者会创建包含文本字段的表单,让...

    SQL 更新指定范围的随机时间

    如果你想要更新表中的所有记录,可以使用`WHERE 1=1`,但这可能会对大量数据进行不必要的操作,因此在实际应用中应谨慎处理。 总结来说,生成指定范围内的时间主要依赖于SQL的日期时间函数和随机数生成函数。具体...

    sqlserver日期函数.pdf

    根据提供的文件内容,以下是对SQL Server中日期函数的知识点总结: 1. GETDATE()函数 这是SQL Server中最常用的一个日期函数,...在使用过程中要特别注意日期格式和语言设置,确保数据库根据预期正确处理日期数据。

    sql server 中使用日期类型的几点心得

    在SQL Server中,日期类型是数据处理中不可或缺的一部分,它涉及到日期和时间的存储、比较、格式化等多个方面。以下是一些使用日期类型的关键知识...在实际操作中,可以根据业务需求和特定场景选择合适的日期处理方法。

    sql结果还原为sql语句 python脚本

    由于一个中文字占两位长度,因此需要特别注意处理以避免语句的断裂。 3. **GBK编码**:GBK是中国大陆广泛使用的汉字编码标准,包含了大部分汉字。在处理包含中文的SQL语句时,必须确保正确解码和编码,以防止字符...

    SQL Server 比较日期大小的方法

    在SQL Server中,比较日期大小是一项基础但至关重要的任务,特别是在处理涉及时间序列的数据时。在上述描述中,提到了一种常见场景,即在机房收费系统中,需要查询特定日期范围内的记录。然而,简单地将用户输入的...

    SQL所有日期函数用法[参考].pdf

    以下是对`DateAdd`、`Day`和`DateDiff`这三个SQL日期函数的详细解释。 1. **DateAdd** 函数: `DateAdd`函数用于在给定的日期基础上添加或减去一个时间段。函数的基本语法是`DateAdd(interval, number, date)`。`...

    Sql语法转换为Oracle语法

    5. 触发器和存储过程:SQL Server和Oracle的语法在创建和调用触发器和存储过程上有所不同,需要特别注意参数传递和返回值的处理。 6. 数据类型:两者的数据类型有差异,例如SQL Server的 `NVARCHAR` 对应Oracle的 `...

    Delphi中sql语句的使用总结

    因此,在构建SQL查询时需要特别注意日期格式。 - **对于Access**:可以使用`#`符号来包围日期,如: ```delphi adoquery1.SQL.Text := 'SELECT ' + AFieldName + ' FROM ' + ATableName + ' WHERE ֶ = #2003-12-...

    SQL Server SQL优化

    在查询时仅返回部分记录可以显著提升查询速度,特别是在处理大数据集时尤为明显。 - **推荐做法**:在满足需求的前提下,使用`TOP`限制返回结果的数量,如`SELECT TOP 1 * FROM A WITH (NOLOCK)`。 - **不推荐做法*...

    如何使用动态SQL生成T-SQL代码?

    以下是对动态SQL生成T-SQL代码的详细解释: 1. **动态SQL的基本概念**: 动态SQL是将SQL语句作为字符串变量构建,然后通过EXEC或sp_executesql系统存储过程执行。这种技术使得SQL语句能够在程序执行过程中动态创建...

    sql 中将日期中分秒化为零的语句

    在SQL中,对日期时间进行处理是常见的操作,特别是在数据清洗、分析或报告时。针对题目中的需求,即“将日期中分秒化为零”,我们可以利用SQL的内置函数进行转换。这里提到的方法是使用`CONVERT`函数,将日期时间...

Global site tag (gtag.js) - Google Analytics