我使用Oracle数据库用C#代码编写了一些集成测试。测试项目有一个CreateDatabase.sql,它包含用于在每次测试执行中创建整个数据库的DDL。
当我只有序列和表时,我在";"
char中分割这个文件的内容并分别执行每个create语句,但现在我有一些函数,它们的语句包含一些{{1其中有字符,所以我不能再使用这种方法了。
我已查看.NET / Oracle: How to execute a script with DDL statements programmatically个问题,但没有帮助。
1)如果我尝试在单个OracleCommand中执行整个文件内容,由于;
字符
ORA-00911: invalid character
2)如果我尝试将文件内容包装在;
中,则会收到错误"begin {0} end;"
3)我可以尝试解析SQL文件并将每个语句放在EXECUTE IMMEDIATE中,但这样会更难......
还有其他选择吗?
我使用Oracle.DataAccess版本4.112.3.0来执行命令。
修改 @kevinsky要求一个脚本,这里是一个简化的例子......整个脚本创建了数百个对象......
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following: ...
答案 0 :(得分:1)
这是一个想法。将前斜杠/
(单独在另一行上)设置为终止脚本中每个语句的新标准方式,而不是依赖于分号。例如,您的示例脚本可能变为:
CREATE SEQUENCE SQ_ARAN_SQ_ARQUIVO_ANEXO
/
CREATE OR REPLACE FUNCTION UFC_SPSW_DISP_COMPOSICAO(p_id_composicao IN NUMBER) RETURN NUMBER
IS
retorno NUMBER:= 0;
numeroItens NUMBER;
temDefinicao BOOLEAN := false;
CURSOR item_cur is
select idc.itdc_sq_item_definicao_composi, idc.insu_sq_insumo, idc.comp_sq_composicao, idc.itdc_nr_coeficiente, idc.COMP_DS_COMPOSICAO, idc.comp_sq_composicao_pai
from item_definicao_composicao idc;
BEGIN
FOR item_rec IN item_cur LOOP
temDefinicao := true;
IF (item_rec.itdc_nr_coeficiente is null) THEN
RETURN null;
ELSE
IF (item_rec.insu_sq_insumo is null) THEN
numeroItens := UFC_SPSW_DISP_COMPOSICAO(nvl(item_rec.comp_sq_composicao_pai, item_rec.comp_sq_composicao));
else
retorno := retorno + 1;
END IF;
END IF;
END LOOP;
IF (temDefinicao = false) THEN
RETURN 0;
END IF;
RETURN retorno;
END;
/
CREATE SEQUENCE SQ_CALC_SQ_CALCULO
/
通过使用/
,如果您希望使用SQL * Plus运行它,您的脚本将保持完全有效。但它现在的优点是,在C#中解析语句变得微不足道,这样你就可以单独执行每个语句而不会出现半冒号问题。
我过去曾使用过这种技术而且运作良好。
(如果您不熟悉在Oracle SQL脚本中使用斜杠,请阅读相关内容:When do I need to use a semicolon vs a slash in Oracle SQL?。)
答案 1 :(得分:1)
我有同样的问题并解决了。 同时使用' BEGIN END'并且'执行立即'。
这是我的测试(成功案例)
begin
EXECUTE IMMEDIATE 'create or replace procedure SP_JHKIM2 IS
begin
dbms_output.put_line(''ABC'');
end;';
end;
答案 2 :(得分:0)
我只使用正则表达式前瞻断言,在LibD
之后进行了分割,然后是一些保留字(或文件的末尾)。
例如:
;