Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 是否支持动态SQL_Oracle_Plsql - Fatal编程技术网

Oracle 是否支持动态SQL

Oracle 是否支持动态SQL,oracle,plsql,Oracle,Plsql,在执行更新时,我们希望对ORA_ROWSCN(Oracle db BTW)进行并发性检查。所以我在考虑创建一个函数,在这个函数中,你传入你拥有的ora_rowscn、表名、列名和一个ID。这个函数将根据你传入的表、列和ID执行一个select语句,如果返回的ora_rowscn与你传入的不同,则返回一个true或false 我对传入的表名和列名进行有效性检查,以确保它们首先存在 FUNCTION ConcurrencyCheck ( pi_orarowscn_in I

在执行更新时,我们希望对ORA_ROWSCN(Oracle db BTW)进行并发性检查。所以我在考虑创建一个函数,在这个函数中,你传入你拥有的ora_rowscn、表名、列名和一个ID。这个函数将根据你传入的表、列和ID执行一个select语句,如果返回的ora_rowscn与你传入的不同,则返回一个true或false

我对传入的表名和列名进行有效性检查,以确保它们首先存在

FUNCTION ConcurrencyCheck (
  pi_orarowscn_in             IN NUMBER,
  pi_table_name               IN VARCHAR2,
  pi_column_name              IN VARCHAR2,
  pi_id                       IN NUMBER


)
  RETURN BOOLEAN IS

r_data_out_of_date BOOLEAN := false;

ln_orarowscn_current NUMBER := 0;

lv_sql VARCHAR2(300) := '';
lv_column VARCHAR(20) := '';
lv_table VARCHAR(20) := '';

BEGIN

SELECT table_name INTO lv_table from ALL_TABLES WHERE TABLE_NAME = pi_table_name;

IF lv_table = '' THEN
  RAISE NO_DATA_FOUND;
ELSE
  SELECT column_name INTO lv_column from USER_TAB_COLUMNS WHERE TABLE_NAME = pi_table_name AND COLUMN_NAME = pi_column_name;

  IF lv_column = '' THEN
    RAISE NO_DATA_FOUND;

  ELSE
    lv_sql := 'select ORA_ROWSCN from ' || pi_table_name || ' where ' || pi_column_name || ' = ' || pi_id || '';
    EXECUTE IMMEDIATE lv_sql INTO ln_orarowscn_current;

    IF ln_orarowscn_current <> pi_orarowscn_in THEN
      r_data_out_of_date := true;
    END IF;

  END IF;      
END IF;

RETURN r_data_out_of_date;



EXCEPTION
    WHEN NO_DATA_FOUND THEN
      RAISE;
    WHEN OTHERS THEN
      RAISE;

  END ConcurrencyCheck;
但是我一直收到一个SQL错误,说表是错误的

另一种解决方案是为所有表创建一个子函数,该子函数将为每个表返回ORA_ROWSCN,并在主函数中创建一个IF ELSE来调用每个表

我在这里寻找最佳实践。现在是否可以接受动态SQL?还是我应该走“长”路线,为每个表创建大量函数/过程


谢谢大家!

对于最佳实践,在这些情况下,建议使用
sys.dbms\u assert

FUNCTION ConcurrencyCheck(
    pi_orarowscn_in             IN NUMBER,
    pi_table_name               IN VARCHAR2,
    pi_column_name              IN VARCHAR2,
    pi_id                       IN NUMBER
)
RETURN BOOLEAN IS
    ln_orarowscn_current NUMBER := 0;
    lv_sql VARCHAR2(300) := '';
BEGIN
    lv_sql := '
        select X.ora_rowscn
        from '||sys.dbms_assert.sql_object_name(pi_table_name)||' X
        where X.'||sys.dbms_assert.simple_sql_name(pi_column_name)||' = :pi_id
    ';
    execute immediate lv_sql
        into ln_orarowscn_current
        using in pi_id;

    return ln_orarowscn_current <> pi_orarowscn_in;
END ConcurrencyCheck;
函数并发检查(
pi_或Rowscn_的数量,
VARCHAR2中的pi_表_名称,
VARCHAR2中的pi_列_名称,
以数字表示的pi_id
)
返回布尔值为
ln_或Rowscn_当前编号:=0;
lv_sql VARCHAR2(300):='';
开始
lv_sql:='
选择X.ora_rowscn
从“| | sys.dbms_assert.sql_object_name(pi_table_name)| |”X
其中X.。|| sys.dbms_assert.simple_sql_name(pi_column_name)||'=:pi_id
';
执行立即lv_sql
进入ln_或Rowscn_电流
在pi_id中使用;
返回ln_或rowscn_当前pi_或rowscn_in;
结束并发检查;

注意:如果我处在你的位置,我会给自己一个艰难的开始,为每个表一次检查的函数包实现一个元数据驱动的代码生成器,正如你可能猜到的那样,这将是静态PL/SQL代码–为你提供所有漂亮的编译时语法/语义检查。

至于最佳实践,在这些情况下,建议使用
sys.dbms\u assert

FUNCTION ConcurrencyCheck(
    pi_orarowscn_in             IN NUMBER,
    pi_table_name               IN VARCHAR2,
    pi_column_name              IN VARCHAR2,
    pi_id                       IN NUMBER
)
RETURN BOOLEAN IS
    ln_orarowscn_current NUMBER := 0;
    lv_sql VARCHAR2(300) := '';
BEGIN
    lv_sql := '
        select X.ora_rowscn
        from '||sys.dbms_assert.sql_object_name(pi_table_name)||' X
        where X.'||sys.dbms_assert.simple_sql_name(pi_column_name)||' = :pi_id
    ';
    execute immediate lv_sql
        into ln_orarowscn_current
        using in pi_id;

    return ln_orarowscn_current <> pi_orarowscn_in;
END ConcurrencyCheck;
函数并发检查(
pi_或Rowscn_的数量,
VARCHAR2中的pi_表_名称,
VARCHAR2中的pi_列_名称,
以数字表示的pi_id
)
返回布尔值为
ln_或Rowscn_当前编号:=0;
lv_sql VARCHAR2(300):='';
开始
lv_sql:='
选择X.ora_rowscn
从“| | sys.dbms_assert.sql_object_name(pi_table_name)| |”X
其中X.。|| sys.dbms_assert.simple_sql_name(pi_column_name)||'=:pi_id
';
执行立即lv_sql
进入ln_或Rowscn_电流
在pi_id中使用;
返回ln_或rowscn_当前pi_或rowscn_in;
结束并发检查;

注意:如果我处在你的位置,我会给自己一个艰难的开始,为每个表一次检查的函数包实现一个元数据驱动的代码生成器,正如你可能猜到的,静态PL/SQL代码–为您提供了所有漂亮的编译时语法/语义检查。

不幸的是,绑定变量不能用于表名或列名,只能用于数据,您别无选择,必须使用动态SQL谢谢回复。这就是我想的。您认为使用动态SQL还是使用一组主函数将调用的过程更好?我不会创建过程,因为您的代码将更难阅读和理解。但我认为还有改进的方法。例如,为什么不立即检查表名和列名的存在性?函数思想也不错,可能返回游标或varray?Cyrille:当然,这应该只是一次检查。谢谢你的意见。Ted:这个函数实际上返回一个布尔值,并且工作正常。我只是想知道安全实现和最佳实践。谢谢不幸的是,bind变量不能用于表名或列名,只能用于数据,您别无选择,必须使用动态sqls。谢谢回复。这就是我想的。您认为使用动态SQL还是使用一组主函数将调用的过程更好?我不会创建过程,因为您的代码将更难阅读和理解。但我认为还有改进的方法。例如,为什么不立即检查表名和列名的存在性?函数思想也不错,可能返回游标或varray?Cyrille:当然,这应该只是一次检查。谢谢你的意见。Ted:这个函数实际上返回一个布尔值,并且工作正常。我只是想知道安全实现和最佳实践。谢谢