Oracle在系统级别上反映元组会触发动态替换感兴趣的字符

Woo*_*Moo 2 sql oracle reflection tuples

我试图编写一个通用触发器,可以检查要插入数据库的每个元组.在这个检查中,我想替换我感兴趣的字符,例如带有常规引号(")的弯引号(MS字).因为我不想为每列写入两个替换调用存储用户提供的数据,我也不想在应用程序中出于多种原因这样做.伪代码如下:

create or replace trigger changeChars
before insert  
on @tableName  
reference new as var
for each row  
Begin 
loop  
:var.@column  := replace(:var.@column,'”', '"');   
end 
Run Code Online (Sandbox Code Playgroud)

Jus*_*ave 5

为什么要替换这些字符?很多人都遇到像Microsoft卷曲引号这样的字符问题,因为这些字符不受数据库字符集的支持,默认情况下,这些字符集导致字符集转换用替换字符替换那些字符,如'?'.如果这是您尝试解决的问题,则数据库代码无法提供帮助,因为在数据甚至到达数据库之前,字符集转换发生在网络层.您可以使用Oracle Locale Builder为客户端计算机构建自定义区域设置,以允许您指定不同的替换字符(即双引号而不是Microsoft卷曲引号).

如果您的问题与字符集无关,则无法创建此类动态触发器.您可以编写一些动态SQL,为每个调用表中REPLACEVARCHAR2列的表创建一个触发器.当然,每次VARCHAR2添加其他列时(通过更改触发器或重新运行PL/SQL块),您都需要维护触发器.

未经测试,我确定生成的DDL不正确,但你需要类似的东西

DECLARE
  l_sql_stmt VARCHAR2(4000);
BEGIN
  FOR tbl IN (SELECT * FROM user_tables)
  LOOP
    l_sql_stmt := 'CREATE OR REPLACE TRIGGER ' || tbl.table_name || '_changeChars ' ||
                  '  BEFORE INSERT ON ' || tbl.table_name ||
                  '  FOR EACH ROW ' ||
                  'BEGIN ';
    FOR col IN (SELECT * FROM user_tab_cols WHERE table_name = tbl.table_name)
    LOOP
      l_sql_stmt := l_sql_stmt ||
                    ' :new.' || col.column_name || 
                        ' := replace( :new.' || col.column_name || ',''"'', ''"''');';
    END LOOP;
    l_sql_stmt := l_sql_stmt || 
                    'END; ';
    dbms_output.put_line( 'SQL statement = ' || l_sql_stmt );
    EXECUTE IMMEDIATE l_sql_stmt;
  END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)