Как я могу передать переменную в сценарий sqlplus и использовать ту же переменную, что и префикс таблицы в запросе Oracle?

У меня есть следующий скрипт sql, а именно check_and_create_tbl.sql

DECLARE
t_count NUMBER;

BEGIN
  SELECT count(*) into t_count FROM all_objects WHERE object_name = '&1_EMPLOYEE' AND object_type = 'TABLE';

  if t_count <= 0 then
    execute immediate 'CREATE TABLE ' || &1 || '_EMPLOYEE (
      ID    NUMBER(3)
    , NAME  VARCHAR2(30) NOT NULL
    )';
  end if;
END;

Теперь я вызываю приведенный выше скрипт в функции моей программы bash, как показано ниже.

function exe_orcl {
  exe_command+=("/opt/bin/sqlplus -s <ORCL_USER>/<ORCL_PASS>@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=<ORCL_HOST>)(PORT=<ORCL_PORT>)))(CONNECT_DATA=(SERVICE_NAME=<ORCL_SNAME>))) ")

  while (( $# > 0 )); do
    exe_command+=("$1")
    shift 1
  done

  echo "SQLPLUS command  =  ${_cmd[@]}"

  "${exe_command[@]}" && { echo "SQLPLUS Success"; } || { echo "SQLPLUS Failed"; }
}

function exe_orcl_sql_file {
  sql_file=$1
  prefix = "TBL_SALE"
  shift 1

  exe_orcl << EOF
  whenever oserror exit 9;
  whenever sqlerror exit SQL.SQLCODE;
  SET NEWPAGE NONE
  @${sql_file} ${prefix} ${@};
  exit
  EOF
}

Теперь в моей программе bash я пытаюсь выполнить файл sql, как показано ниже.

exe_orcl_sql_file "/tmp/check_and_create_tbl.sql" || { echo "SQLPLUS execution error"; }

Я вижу журнал, как показано ниже.

SQLPLUS command  =  /opt/bin/sqlplus -s XXXX/XXXX@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=XXXX)(PORT=XXXX)))(CONNECT_DATA=(SERVICE_NAME=XXXX))) 

SQLPLUS Success

Но я не вижу TBL_SALE_EMPLOYEE, созданного в Oracle DB, подскажите, что мне здесь не хватает?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
0
0
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы должны помнить, что переменная вводится с помощью sql*plus, вы также должны понимать, что '_' является допустимой частью имени переменной, поэтому вам нужно четко указать, где должен быть конец.

DECLARE
t_count NUMBER;

BEGIN
  SELECT count(*) into t_count FROM all_objects WHERE object_name = '&1._EMPLOYEE' AND object_type = 'TABLE';

  if t_count <= 0 then
    execute immediate 'CREATE TABLE  &1._EMPLOYEE (
      ID    NUMBER(3)
    , NAME  VARCHAR2(30) NOT NULL
    )';
  end if;
END;
/

Спасибо, Андрей, если я уберу / из последней строки, таблица не создастся. Я не хочу, чтобы запросы печатались на консоли.

axnet 14.12.2020 14:31
/ — отправить выписку в базу данных. Не совсем уверен, что вы видите и что вы не хотите видеть, но ваш переключатель -s в вызове sqlplus в любом случае должен предотвращать запись чего-либо на консоль с помощью sqlplus.
Andrew Sayer 14.12.2020 14:33

Кроме того, в обоих случаях, когда t_count = 1 и когда t_count = 0, я вижу, что ** выполнить немедленное «CREATE TABLE TBL_SALE_EMPLOYEE **» печатается на консоли, что заставило меня задуматься, действительно ли условие работает или нет.

axnet 14.12.2020 14:37

Клиент (sqlplus) ничего не знает о том, что выполняется в базе данных, если нет какой-либо обратной связи (dbms_output и т. д.), все, что он знает, это то, что он отправил анонимный блок и был либо успешно выполнен, либо завершился ошибкой. Я не уверен, откуда исходит эхо чего-либо — я не думаю, что это SQL*plus, если только у вас нет скрипта (g)login.sql, выполняющего set echo on.

Andrew Sayer 14.12.2020 15:10

Другие вопросы по теме