【问题标题】:I can use a timestamp variable on query of cursor in a store procedure?我可以在存储过程中查询游标时使用时间戳变量吗?
【发布时间】:2016-05-31 05:27:45
【问题描述】:

我需要一个可以动态更改的时间戳变量,但是当我尝试将此时间戳变量传递给语句时,这不起作用:

没有时间戳变量,它可以工作:

CREATE OR REPLACE
PROCEDURE "PR_TEST"( sl_cursor OUT SYS_REFCURSOR)  
IS
    stm VARCHAR2(3000);
    var_ativo number:= 1 ;
BEGIN
    stm := 'SELECT
               *
        FROM
            SIMET.TB_1 SC
            JOIN SIMET.TB_2 D ON D.HASH = SC.HASH
        WHERE
             SC.IS_ACTIVE = ' || var_ativo ;            
     OPEN sl_cursor FOR  stm ;
END;

但使用 timestamp var ,它不起作用:

CREATE OR REPLACE
PROCEDURE "PR_TEST"( sl_cursor OUT SYS_REFCURSOR)  
IS
    stm VARCHAR2(3000);
    var_ativo number:= 1 ;
    var_ts timestamp := SYSTIMESTAMP
BEGIN
    stm := 'SELECT
               *
        FROM
            SIMET.TB_1 SC
            JOIN SIMET.TB_2 D ON D.HASH = SC.HASH
        WHERE
             SC.IS_ACTIVE = ' || var_ativo 
         AND 
             sc.timestamp = ' || var_ts

     OPEN sl_cursor FOR  stm ;
END;

有人知道我是怎么做到的吗?

【问题讨论】:

  • 这些查询似乎都不需要动态 SQL。您真的、真的、真的确定需要动态 SQL 方法,而不仅仅是使用静态 SQL?
  • 你试过 GetDate() 吗?为什么要使用动态 SQL 而不是直接使用 SQL?
  • 我为此使用动态 sql,因为我的完整查询花费了很多时间来返回选择,并且在选择之后我需要在每个结果中进行更新,(大约 300 万)和数据库停止。然后我决定在较小的查询中分开,我将做一个循环,我将每天更改日期。有人会建议另一种方法吗?
  • 对不起我的(糟糕的)英语,我正在努力提高这一点。
  • 这甚至不像 t-sql 这是一个 CLR proc?为什么要使用一个来完成可以在 t-sql 中完成的事情?在 proc 中一次更新 300 万条记录是一个非常糟糕的主意。您可能仍需要循环,但您希望分批运行记录,而不是一次运行一条记录的典型游标。请详细说明您要完成的工作,以便我们向您展示实现目标的最佳方式。目前没有足够的信息来确定您需要什么,因为您在选择后引用了更新并且没有向我们显示代码。

标签: sql oracle stored-procedures plsql


【解决方案1】:

直接的问题是你没有正确地连接你的字符串;您也需要将 AND 作为文字的一部分。而且你少了一个分号。

stm := 'SELECT
           *
    FROM
        SIMET.TB_1 SC
        JOIN SIMET.TB_2 D ON D.HASH = SC.HASH
    WHERE
         SC.IS_ACTIVE = ' || var_ativo || '
     AND 
         sc.timestamp = ' || var_ts;

但是现在您正在将您的 v_ts 变量隐式转换为字符串。作为一个字符串,它需要用转义的单引号括起来:

         sc.timestamp = ''' || var_ts || '''';

但这涉及到更多隐式转换以与列值进行比较,因此您确实希望以两种方式显式转换它。正如您可能想象的那样,这有点危险,表明您做错了。

如果您使用的是动态 SQL,那么您应该使用绑定变量:

stm := 'SELECT
           *
    FROM
        SIMET.TB_1 SC
        JOIN SIMET.TB_2 D ON D.HASH = SC.HASH
    WHERE
         SC.IS_ACTIVE = :ativo
     AND 
         sc.timestamp = :ts';

 OPEN sl_cursor FOR stm USING var_ativo, var_ts;

但从您所展示的内容来看,您根本不应该在这里使用动态 SQL:

 OPEN sl_cursor FOR
    SELECT
           *
    FROM
        SIMET.TB_1 SC
        JOIN SIMET.TB_2 D ON D.HASH = SC.HASH
    WHERE
         SC.IS_ACTIVE = var_ativo 
     AND 
         sc.timestamp = var_ts;

引用汤姆·凯特的话:“You use dynamic sql only when there is quite simply NO WAY to do it statically.

您的前提是将您所做的任何事情拆分为较小的查询和更新可能是不正确的,您可能会使其整体变慢;但这是一个单独的问题,需要更多信息才能解决。

【讨论】:

猜你喜欢
  • 2013-08-27
  • 1970-01-01
  • 2011-02-04
  • 2021-12-02
  • 1970-01-01
  • 1970-01-01
  • 2021-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多