我正在尝试编写一个sqlplus命令,该命令根据存储在.sql文件中的查询创建一个表。
包含查询的特定.sql文件将作为变量(&v_InputQuery
)提供给我的sqlplus命令。
我尝试过类似的东西,但它不起作用。
CREATE TABLE &v_OutputTable AS
(
< &v_InputQuery
)
;
我收到一条错误消息,说明缺少SELECT关键字。
我真正喜欢的是&v_InputQuery
不是用用户指定的文件名替换,而是用文件的实际内容替换。有没有办法做到这一点?
非常感谢你。
答案 0 :(得分:3)
是的,你可以这样做。如果您的查询位于名为v_InputQuery.sql
的文件中,则可以执行以下操作:
CREATE TABLE &v_OutputTable AS (
@v_InputQuery.sql
) ;
@
是该行的第一个字符非常重要。 SQL * Plus将读取该文件并将其内容放在该位置。因此,请确保文件中没有任何终止字符,例如;
或/
。
答案 1 :(得分:2)
不幸的是,您无法创建SQL * Plus命令,而是创建一个shell脚本来执行此操作!
让我们说my_script.sh
低于
#you can always complete the user interaction at unix/dos
USER=your_user
PASS=your_pass
DB=your_db
OUTPUT_TABLE=$1;
QUERY_FILE=$2;
SELECT_QUERY=`cat $QUERY_FILE`;
sqlplus -S ${USER}/${PASS}@${DB} << !
SET SERVEROUTPUT ON;
VAR EXITCODE NUMBER;
BEGIN
EXECUTE IMMEDIATE ' CREATE TABLE $OUTPUT_TABLE AS $SELECT_QUERY ';
:EXITCODE := SQLCODE;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
:EXITCODE := SQLCODE;
END;
/
exit :EXITCODE
!
执行以下脚本(取决于操作系统)
ksh my_script MY_OUTPUT_TABLE my_sql.sql;
答案 2 :(得分:2)
扩展评论,@ MaheswaranRavisankar的方法可行,但动态SQL(即execute immediate
)不是必需的,因此匿名块也不是必需的。它可以简化为:
USER=your_user
PASS=your_pass
DB=your_db
OUTPUT_TABLE=$1;
QUERY_FILE=$2;
SELECT_QUERY=`cat $QUERY_FILE`;
sqlplus -S ${USER}/${PASS}@${DB} << !
WHENEVER SQLERROR EXIT FAILURE
CREATE TABLE $OUTPUT_TABLE AS $SELECT_QUERY
!
这也允许您使用已由;
或/
终止的查询,execute immediate
版本不喜欢 - 您只需要确定您的包装是否脚本需要一个匹配查询文件将包含的内容。
即使whenever ...
行也不重要,但另一个答案试图退出错误代码,所以我太模仿了。这将始终以通用故障状态退出(在Unix中为1
,不确定Windows的作用)。然后,如果您愿意,可以在脚本中使用$?
测试它是否成功。
您可以使用whenever sqlerror exit sql.sqlcode
来替换实际的SQL错误而不是通用值。这样做的问题是大多数(全部?)shell将返回代码限制在0-255范围内,因此大多数错误都会包装并提供无用的东西 - 一个相当可能的ORA-00955: name is already used by an existing object
错误会导致shell退出例如,值为187。并且包装的值可能为零,这将掩盖发生的错误;一个似乎合理的ORA-01536: space quota exceeded for tablespace '%s'
错误会使shell退出代码为零,这是无益的。使用exit failure
至少会阻止它。