Можно ли передать имя таблицы в качестве параметра в Oracle? - PullRequest
1 голос
/ 11 сентября 2010

Я хочу создать хранимую процедуру следующим образом:

PROCEDURE P_CUSTOMER_UPDATE
  (
      pADSLTable IN Table,
      pAccountname IN NVARCHAR2,
      pStatus IN NUMBER,
      pNote IN NVARCHAR2,
      pEmail IN NVARCHAR2,
      pMobi IN NVARCHAR2,
      pServiceTypeID IN NUMBER,
      pDate IN DATE
  )
  IS
  BEGIN
      UPDATE pADSLTable
      SET STATUS = pStatus, NOTE = pNote, EMAIL = pEmail, MOBI = pMobi, SERVICETYPE_ID = pServiceTypeID, ACTIVATION_DATE = pDate
      WHERE ACCOUNT_NAME = pAccountname;
  END;

Конечно, Oracle не позволяет мне этого делать. Есть ли способ обойти эту проблему? Большое спасибо.

Ответы [ 3 ]

12 голосов
/ 11 сентября 2010

У вас есть несколько разных таблиц с одинаковыми именами столбцов и типами данных?Пахнет как изворотливый дизайн.

В любом случае, мы не можем использовать переменные в качестве объектов базы данных в прямом SQL-коде.Мы должны использовать динамический SQL.

PROCEDURE P_CUSTOMER_UPDATE
  (
      pADSLTable IN USER_TABLES.table_name%type,
      pAccountname IN NVARCHAR2,
      pStatus IN NUMBER,
      pNote IN NVARCHAR2,
      pEmail IN NVARCHAR2,
      pMobi IN NVARCHAR2,
      pServiceTypeID IN NUMBER,
      pDate IN DATE
  )
  IS
  BEGIN
      execute immediate 
          'UPDATE '||pADSLTable
          ||' SET STATUS = :1, NOTE = :2, EMAIL = :3, MOBI = :4, SERVICETYPE_ID = :5, ACTIVATION_DATE = :6'
          ||' WHERE ACCOUNT_NAME = :7'
      using pStatus, pNote, pEmail, pMobi, pServiceTypeID, pDate, pAccountname;
  END;

Одна из причин, по которой следует избегать использования динамического SQL, заключается в том, что он открыт для злоупотреблений.Злоумышленники могут использовать параметры, чтобы попытаться обойти нашу безопасность.Это называется инъекцией SQL.Я думаю, что люди переоценивают значение SQL-инъекций.Это не автоматически угроза.Например, если процедура является частной процедурой в пакете (т. Е. Не объявлена ​​в спецификации), маловероятно, что кто-нибудь ее похитит.

Но разумно принять меры предосторожности.DBMS_ASSERT - это пакет, введенный в Oracle 10g для отлова попыток внедрения SQL-кода.В этом случае стоило бы использовать его для проверки переданного имени таблицы

....
'UPDATE '|| DBMS_ASSERT.simple_sql_name(pADSLTable)
....  

. Это предотвратит передачу кем-либо 'pay_table set salary = salary * 10 where id = 1234 --' в качестве параметра имени таблицы.

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

Наконец, такой динамический SQL не отображается в представлениях, таких как ALL_DEPENDENCIES.Это затрудняет проведение анализа воздействия и поиск всех программ, которые используют данную таблицу или столбец.

1 голос
/ 11 сентября 2010

Да, существует собственный динамический SQL:

EXECUTE IMMEDIATE 'UPDATE ' || pADSLTable || 
  'SET STATUS = :1, NOTE = :2, EMAIL = :3, MOBI = :4, SERVICETYPE_ID = :5, ACTIVATION_DATE = :6 WHERE ACCOUNT_NAME = :7 '  
  USING pStatus, pNote, pEmail, pMobi, pServiceTypeId, pDate, pAccountname;

Производительность и проверка ошибок не так хороши (нет синтаксиса во время компиляции и проверки схемы).Остерегайтесь SQL-инъекций.

Итак, если у вас есть только несколько таблиц на выбор, рассмотрите возможность использования конструкции if / then / else со всеми опциями.

0 голосов
/ 13 сентября 2010

Вы можете использовать все виды операторов DDL, используя динамический SQL.Вы можете передавать имена различных объектов базы данных в качестве параметров или манипулировать переменными.

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