Отражение Oracle в кортеже на триггере системного уровня для динамической замены символов, представляющих интерес - PullRequest
2 голосов
/ 03 августа 2011

Я пытаюсь написать общий триггер, который может проверять каждый кортеж, который должен быть вставлен в базу данных. В этой проверке я хочу заменить символы, которые меня интересуют, такие как фигурные кавычки (MS word), на обычные кавычки ("). Так как я не хочу писать два вызова замены для каждого столбца, который хранит данные, предоставленные пользователем, и я не хочу делать это в приложении по множеству причин. Псевдокод выглядит следующим образом:

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

Ответы [ 2 ]

5 голосов
/ 03 августа 2011

Почему вы хотите заменить этих персонажей? Многие люди имеют проблемы с символами, такими как фигурные кавычки Microsoft, потому что эти символы не поддерживаются их набором символов базы данных, который, по умолчанию, заставляет преобразование набора символов заменять те символы заменой символов как '?'. Если это проблема, которую вы пытаетесь решить, код базы данных не может помочь, потому что преобразование набора символов происходит на сетевом уровне еще до того, как данные попадают в базу данных. Потенциально вы могли бы использовать Oracle Locale Builder для создания собственной локали для ваших клиентских компьютеров, которая позволяла бы вам указывать различные замещающие символы (то есть двойные кавычки, а не фигурные кавычки Microsoft).

Если ваша проблема не связана с набором символов, нет способа создать такой динамический триггер. Вы могли бы написать немного динамического SQL, который создавал бы триггер для каждой таблицы с именем REPLACE в каждом столбце VARCHAR2 в таблице. Конечно, вам нужно будет поддерживать триггер каждый раз, когда добавляется дополнительный столбец 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;
2 голосов
/ 03 августа 2011

Хорошо, так что проще всего построить функцию для замены.

create or replace function strip_quotes
    (p_str in varchar2)
    return varchar2
is
begin
    return translate(p_str, chr(145)||chr(146)||chr(147)||chr(148), chr(39)||chr(39)||chr(34)||chr(34));
end;
/

145–148 - расширенные значения ASCII для MS Smart Quotes, одинарные и двойные. Мы можем использовать это так:

SQL> select strip_quotes('ôHiö said Jon.') from dual
  2  /

STRIP_QUOTES('ôHIöSAIDJON.')
-------------------------------------------------------------------------------
"Hi" said Jon.

SQL>

Труднее всего отражение. Я согласен с Джастином, что генерация триггера для каждой таблицы является лучшим решением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...