Ошибка: DPI-1059: переменные связывания не поддерживаются в операторах DDL при вызове процедуры с использованием node-oracledb

Я создал хранимую процедуру ниже в sql-developer:

CREATE OR REPLACE PROCEDURE CREATE_USER(
 t_username IN VARCHAR2, 
 t_password IN VARCHAR2,
 t_default_table IN VARCHAR2,
 t_quota IN VARCHAR2
)
IS
    m_statement VARCHAR2(1300);
    
    m_username VARCHAR2(30) := t_username;
    m_password VARCHAR2(30) := t_password;
    m_default_table VARCHAR2(30) := t_default_table;
    m_quota VARCHAR2(30) := t_quota;
    
BEGIN
    m_statement := 'create user ' || t_username || ' identified by ' || t_password;

    IF m_default_table != 'NULL' THEN
         m_statement := m_statement || ' DEFAULT TABLESPACE ' || m_default_table;
    END IF;

    IF m_quota != '0' AND m_default_table != 'NULL' THEN
        m_statement := m_statement || ' QUOTA ' || m_quota || 'M ON ' || m_default_table;
    END IF;
    EXECUTE IMMEDIATE (m_statement);
END;

И это скомпилировано без ошибок. Я также подключился к оракулу. Затем я получил пользовательские данные (req.body) следующим образом:

{ username: 'a', password: 'a', tablespace: 'NULL', quota: '0' }

Но когда я выполняю запрос процедуры «вызов»:

oracle.getConnection(
        {
            uuser : "AN",
            password: "AN123",
            connectString: "localhost:1521/orcl"
        },
        (t_err, t_connection) => {
            if(t_err){
                console.error(t_err);
                return;
            }
            t_connection.execute(
                `BEGIN 
                    createUser(:username, :password, :tablespace, :quota);
                END;`,
                {
                    username: req.body.username,
                    password: req.body.password,
                    tablespace: req.body.tablespace,
                    quota: req.body.quota,
                    
                },
                (t_er, t_reslt) => {
                    if(t_er){
                        console.error(t_er);
                        return;
                    }

Я получил:

[Error: DPI-1059: bind variables are not supported in DDL statements] {
  errorNum: 0,
  offset: 0
}

Я пробовал много способов исправить процедуру или код nodejs, но это не сработало. Я очень новичок в этой теме. Кто-нибудь может мне помочь?


person Nguyen Bot    schedule 05.04.2021    source источник
comment
Пожалуйста, взгляните на пример файла документации. github.com/oracle/node-oracledb/blob/master/ примеры/   -  person wolφi    schedule 05.04.2021
comment
@волфии. Я это уже видел. Все мои параметры являются параметрами IN. Поэтому я просто присваиваю им значение в Req.body.x. Это правда по ссылке, которую вы мне дали?   -  person Nguyen Bot    schedule 05.04.2021
comment
Есть ли способ не использовать оператор dll?   -  person Nguyen Bot    schedule 05.04.2021
comment
Я совершенно не знаком с node-oracledb. Вы правы, в примере указано, что значение по умолчанию включено. Однако у меня возникло бы искушение указать тип данных и направление username: { type: oracledb.STRING, dir: oracle_db.BIND_IN}. Кроме того, я бы упростил пример, например, сначала создал таблицу с жестко заданным именем, процедуру без каких-либо параметров, затем добавил параметр для имени таблицы и медленно продвигался к вашему примеру. Также проверьте использование разных имен переменных, возможно, одно из них является зарезервированным ключевым словом.   -  person wolφi    schedule 05.04.2021
comment
Есть еще две возможности: 1) В PL/SQL это называется CREATE_USER, вызывающий код использует createUser, но я полагаю, что это опечатка. 2) Есть ли лишняя запятая в строке quota: req.body.quota,?   -  person wolφi    schedule 05.04.2021
comment
@wolφi, я сделал то, что вы сказали, и получил ORA-01036: недопустимое имя/номер переменной. Кстати, я удалил лишнюю запятую.   -  person Nguyen Bot    schedule 05.04.2021


Ответы (2)


Ваш код работает без ошибок для меня - как только я исправляю конфликт между именем в операторе SQL CREATE_USER и именем в файле JS createUser. Действительно убедитесь, что вы не вызываете какую-либо предыдущую версию пакета PL/SQL, которая пытается использовать переменные связывания в операторе CREATE USER (это было отмечено в комментариях). Как указано в ошибке: это использование не поддерживается Oracle DB. Например, вы не можете сделать:

connection.execute(`create user :un identified by :pw`, ['cj2', 'cj2password']);
  • Это оператор DDL
  • Он пытается использовать переменные связывания

И это не поддерживается. И это не удается с DPI-1059. Переменные связывания используются для данных, а не для текста операторов.

Еще два совета:

  • Фильтруйте или дезинфицируйте входные значения, чтобы избежать атак SQL Injection.
  • Используйте стиль программирования async/await (вместо обратных вызовов), чтобы избавить себя от головной боли. Посмотрите все примеры node-oracledb.
person Christopher Jones    schedule 06.04.2021

Код ошибки DPI-1059 выглядит незнакомым, не похожим на сообщение об ошибке Oracle. Я проверил node-oracledb, они используют с NJS-000 по NJS-080. Поиск в Google привел к интерфейсу программирования баз данных Oracle для C, который определяет этот код ошибки в dpiErrorMessages.h:

"DPI-1059: bind variables are not supported in DDL statements", // DPI_ERR_NO_BIND_VARS_IN_DDL

Константа DPI_ERR_NO_BIND_VARS_IN_DDL используется только один раз в исходном коде, в файле dpiStmt. .с:

// attempt to improve message "ORA-01036: illegal variable name/number"
if (status < 0) {
    if (error->buffer->code == 1036) {
        if (stmt->statementType == DPI_STMT_TYPE_CREATE ||
                stmt->statementType == DPI_STMT_TYPE_DROP ||
                stmt->statementType == DPI_STMT_TYPE_ALTER)
            dpiError__set(error, error->buffer->action,
                    DPI_ERR_NO_BIND_VARS_IN_DDL);
    }
    return DPI_FAILURE;
}

Поскольку сообщения об ошибках Oracle очень запутаны, стоит изучить ORA-01036, например здесь

person wolφi    schedule 05.04.2021