简体   繁体   English

如何使用 asp.net (vb.net) 执行 Oracle.SQL 脚本文件

[英]How to execute an Oracle .SQL script file using asp.net (vb.net)

The overall goal of what I am trying to do here is execute an Oracle SQL Script from as asp.net (vb.net) web application that has SQL*Plus commands in it that queries the data and drops the results to a text file and then display the text file to the end user of the web application. The overall goal of what I am trying to do here is execute an Oracle SQL Script from as asp.net (vb.net) web application that has SQL*Plus commands in it that queries the data and drops the results to a text file and then display将文本文件发送给 web 应用程序的最终用户。 I am running into a problem attempting to execute the.sql file in my visual studio code it tells me that it is not a valid SQL statement.我在尝试在我的 Visual Studio 代码中执行 .sql 文件时遇到问题,它告诉我它不是有效的 SQL 语句。 Of course that makes sense because there is more in the.sql file than a sql statement.当然这是有道理的,因为 .sql 文件中的内容比 sql 语句更多。

I am using .NET version 4.6.1 in my Visual Studio project and I am calling an Oracle 11 database.我在我的 Visual Studio 项目中使用 .NET 版本 4.6.1,我正在调用 Oracle 11 数据库。

Here is the code that I am trying to execute.这是我要执行的代码。 When it gets to the line where it is attempting to execute the script it throws the following error:当它到达尝试执行脚本的行时,它会引发以下错误:

ERROR: Oracle.OracleException: 'ORA-00900: invalid SQL statement'错误:Oracle.OracleException:'ORA-00900:无效的 SQL 语句'

Here is the VB.NET code:这是 VB.NET 代码:

Dim OracleConnection As OracleConnection = New OracleConnection()
OracleConnection.ConnectionString = Settings.GetOracleConnectionString
OracleConnection.Open()
Dim script As String = File.ReadAllText("C:\OracleScripts\p_sum.sql")

Dim command As OracleCommand = OracleConnection.CreateCommand()
command.CommandText = script
command.ExecuteNonQuery()   << Errors on this line

The.sql file makes a few calls to Oracle and then exports (spools) the results to a.txt file. .sql 文件对 Oracle 进行几次调用,然后将结果导出(假脱机)到 a.txt 文件。 Once the.sql script is executed I would then display the.txt file that is created in the browser.一旦执行了 .sql 脚本,我就会显示在浏览器中创建的 .txt 文件。

I have provided a copy of the.sql file below:我在下面提供了 .sql 文件的副本:

SPOOL data/p_sum.txt
PROMPT REPORT P_SUM.SQL Rev.04 (MIXER=&&MIXER) (CMPD=&&CMPD) (START=&&START) (END=&&END)
SET VERIFY OFF
SET LINESIZE 130

CLEAR BREAKS
CLEAR COMPUTES

COLUMN SHIFT_DT         FORMAT A6       HEADING Shift|Date
COLUMN SHIFT_NUM    FORMAT B9       HEADING Sh|#
COLUMN MIXER_NUM    FORMAT B99      HEADING Mix|Num
COLUMN RUN_START_DT FORMAT A12      HEADING Shift|Start
COLUMN COMPOUND     FORMAT A11      HEADING |Compound
COLUMN BAG_NAME     FORMAT A11      HEADING 'Bag Name'
COLUMN BAG_MIXER_NUM    FORMAT B99      HEADING Bag|Usr
COLUMN BATCH_CNT    FORMAT B99,999      HEADING Good|Cnt
COLUMN ERROR_CNT    FORMAT B999     HEADING Bad|Cnt
COLUMN EDIT_CNT     FORMAT B999     HEADING Edt|Cnt
COLUMN WT_PROD      FORMAT B999,999     HEADING Lbs/Kg|Produced
COLUMN TCHARGE      FORMAT B9999.9      HEADING Cycle|Min
COLUMN TDELAY       FORMAT B9999.9      HEADING Delay|Min
COLUMN TCHANGE      FORMAT B9999.9      HEADING Change|Min
COLUMN TNOTSCHED    FORMAT B9999.9      HEADING Unschd|Min
COLUMN RUN      FORMAT B99,999      HEADING Run|Min
COLUMN Avg_CHARGE   FORMAT B9.99        HEADING Cycle|Avg
COLUMN pct_up       FORMAT B999.9       HEADING '% Up|Time'

BREAK ON SHIFT_DT SKIP 1
CLEAR &&CLAUSE1

SELECT TO_CHAR(SHIFT_DT,' MM/DD') SHIFT_DT,
 R.SHIFT_NUM,
 TO_CHAR(MIN(R.RUN_START_DT),' MM/DD HH24:MI') RUN_START_DT,
 '*SHIFT' COMPOUND,
 'TOTAL ' BAG_NAME,
 SUM(R.BATCH_CNT)-NVL(SUM(R.ERROR_CNT),0) BATCH_CNT,
 SUM(R.ERROR_CNT) ERROR_CNT,
 SUM(EDIT_CNT)    EDIT_CNT,
 SUM(R.WT_PROD)   WT_PROD,
 SUM(R.TCHARGE)   TCHARGE,
 SUM(R.TDELAY)    TDELAY,
 SUM(R.TCHANGE)   TCHANGE,
 SUM(R.TNOTSCHED) TNOTSCHED,
 NVL(SUM(R.TCHARGE),0)+NVL(SUM(R.TDELAY),0)+NVL(SUM(R.TCHANGE),0)+NVL(SUM(R.TNOTSCHED),0) RUN,
 DECODE(SUM(R.BATCH_CNT)-SUM(R.ERROR_CNT),0,0,SUM(R.TCHARGE)/(SUM(R.BATCH_CNT)-SUM(R.ERROR_CNT))) AVG_CHARGE,
 SUM(R.TCHARGE)*100/(NVL(SUM(R.TCHARGE),0)+NVL(SUM(R.TDELAY),0)+NVL(SUM(R.TCHANGE),0)) PCT_UP
FROM MIXER.RUN_SUMM R, MIXER.SPEC S
WHERE R.SPEC_NUM=S.SPEC_NUM
  AND R.MIXER_NUM IN(&&MIXER)
  AND R.MIXER_NUM >=80
  AND SHIFT_DT BETWEEN TO_DATE('&&START','MM/DD/RR') AND TO_DATE('&&END','MM/DD/RR')
GROUP BY R.SHIFT_DT, R.SHIFT_NUM
UNION
SELECT TO_CHAR(R.SHIFT_DT,' MM/DD') SHIFT_DT,
 0 SHIFT_NUM,
 'ALL SHIFTS' RUN_START_DT,
 '**DAILY' COMPOUND,
 'TOTAL' BAG_NAME,
 SUM(R.BATCH_CNT)-NVL(SUM(R.ERROR_CNT),0) BATCH_CNT,
 SUM(R.ERROR_CNT) ERROR_CNT,
 SUM(EDIT_CNT)    EDIT_CNT,
 SUM(R.WT_PROD)   WT_PROD,
 SUM(R.TCHARGE)   TCHARGE,
 SUM(R.TDELAY)    TDELAY,
 SUM(R.TCHANGE)   TCHANGE,
 SUM(R.TNOTSCHED) TNOTSCHED,
 NVL(SUM(R.TCHARGE),0)+NVL(SUM(R.TDELAY),0)+NVL(SUM(R.TCHANGE),0)+NVL(SUM(R.TNOTSCHED),0) RUN,
 DECODE(SUM(R.BATCH_CNT)-SUM(R.ERROR_CNT),0,0,SUM(R.TCHARGE)/(SUM(R.BATCH_CNT)-SUM(R.ERROR_CNT))) AVG_CHARGE,
 SUM(R.TCHARGE)*100/(NVL(SUM(R.TCHARGE),0)+NVL(SUM(R.TDELAY),0)+NVL(SUM(R.TCHANGE),0)) PCT_UP
FROM MIXER.RUN_SUMM R, MIXER.SPEC S
WHERE R.SPEC_NUM=S.SPEC_NUM
  AND R.MIXER_NUM IN(&&MIXER)
  AND R.MIXER_NUM >=80
  AND SHIFT_DT BETWEEN TO_DATE('&&START','MM/DD/RR') AND TO_DATE('&&END','MM/DD/RR')
GROUP BY R.SHIFT_DT
UNION
SELECT 'ALL' SHIFT_DT,
 0 SHIFT_NUM,
 ' ' RUN_START_DT,
 '***GRAND' COMPOUND,
 'TOTAL' BAG_NAME,
 SUM(R.BATCH_CNT)-NVL(SUM(R.ERROR_CNT),0) BATCH_CNT,
 SUM(R.ERROR_CNT) ERROR_CNT,
 SUM(EDIT_CNT)    EDIT_CNT,
 SUM(R.WT_PROD)   WT_PROD,
 SUM(R.TCHARGE)   TCHARGE,
 SUM(R.TDELAY)    TDELAY,
 SUM(R.TCHANGE)   TCHANGE,
 SUM(R.TNOTSCHED) TNOTSCHED,
 NVL(SUM(R.TCHARGE),0)+NVL(SUM(R.TDELAY),0)+NVL(SUM(R.TCHANGE),0)+NVL(SUM(R.TNOTSCHED),0) RUN,
 DECODE(SUM(R.BATCH_CNT)-SUM(R.ERROR_CNT),0,0,SUM(R.TCHARGE)/(SUM(R.BATCH_CNT)-SUM(R.ERROR_CNT))) AVG_CHARGE,
 SUM(R.TCHARGE)*100/(NVL(SUM(R.TCHARGE),0)+NVL(SUM(R.TDELAY),0)+NVL(SUM(R.TCHANGE),0)) PCT_UP
FROM MIXER.RUN_SUMM R, MIXER.SPEC S
WHERE R.SPEC_NUM=S.SPEC_NUM
  AND R.MIXER_NUM IN(&&MIXER)
  AND R.MIXER_NUM >=80
  AND SHIFT_DT BETWEEN TO_DATE('&&START','MM/DD/RR') AND TO_DATE('&&END','MM/DD/RR')
ORDER BY SHIFT_DT,RUN_START_DT;

COLUMN SHIFT_DT         FORMAT A5       HEADING Shift|Date
COLUMN RUN_START_DT FORMAT A11      HEADING Run|Start
COLUMN COMPOUND     FORMAT A10      HEADING |Compound
COLUMN BAG_NAME     FORMAT A10      HEADING 'Bag Name'

BREAK ON SHIFT_DT SKIP PAGE ON SHIFT_NUM SKIP 1
CLEAR &&CLAUSE1

SELECT TO_CHAR(SHIFT_DT,'MM/DD') SHIFT_DT,
 R.SHIFT_NUM,
 TO_CHAR(RUN_START_DT,'MM/DD HH24:MI') RUN_START_DT,
 S.COMPOUND,
 R.BAG_NAME,
 R.BAG_MIXER_NUM,
 R.BATCH_CNT-NVL(R.ERROR_CNT,0) BATCH_CNT,
 R.ERROR_CNT,
 R.EDIT_CNT,
 R.WT_PROD,
 R.TCHARGE,
 R.TDELAY,
 R.TCHANGE,
 R.TNOTSCHED,
 NVL(R.TCHARGE,0)+NVL(R.TDELAY,0)+NVL(R.TCHANGE,0)+NVL(R.TNOTSCHED,0) RUN,
 DECODE(R.BATCH_CNT-NVL(R.ERROR_CNT,0),0,0,R.TCHARGE/(R.BATCH_CNT-NVL(R.ERROR_CNT,0))) AVG_CHARGE
FROM MIXER.RUN_SUMM R, MIXER.SPEC S
WHERE R.SPEC_NUM=S.SPEC_NUM
  AND R.MIXER_NUM IN(&&MIXER)
  AND R.MIXER_NUM >=80
  AND SHIFT_DT BETWEEN TO_DATE('&&START','MM/DD/RR') AND TO_DATE('&&END','MM/DD/RR')
  AND ROWNUM<=&&ROWLIMIT
ORDER BY SHIFT_DT,RUN_START_DT;

SPOOL OFF
SET VERIFY ON
CLEAR BREAKS
CLEAR COMPUTES

Unfortunately, your VB.NET code has no idea what to do with all the SQL*Plus commands embedded in your script.不幸的是,您的 VB.NET 代码不知道如何处理脚本中嵌入的所有SQL*Plus命令。 SQL*Plus is the only application that supports the full set of commands. SQL*Plus是唯一支持全套命令的应用程序。 SQL Developer supports a subset of the SQL*Plus commands. SQL Developer 支持SQL*Plus命令的子集。 It looks like SQL Developer would support all the SQL*Plus commands in this particular script but I'd need to go through the documentation to be sure.看起来 SQL Developer 将支持此特定脚本中的所有SQL*Plus命令,但我需要通过文档确定 go。

The quick and dirty solution would be to shell out to the operating system from VB and invoke SQL*Plus to produce the file and then let VB.NET return the file to the client.快速而肮脏的解决方案是将 shell 从 VB 输出到操作系统并调用SQL*Plus生成文件,然后让 VB.NET 将文件返回给客户端。 That's not particularly elegant and you'd have a problem in a multi-user environment because the script would try to spool the same file from two different sessions if it was called with the same parameters.这不是特别优雅,并且在多用户环境中会遇到问题,因为如果使用相同的参数调用脚本,它将尝试从两个不同的会话中假脱机相同的文件。 But it appears that the legacy solution has the same multi-user problem already.但似乎遗留解决方案已经存在相同的多用户问题。

The more elegant solution would be to refactor the scripts to move as much of the logic as possible into a view.更优雅的解决方案是重构脚本以将尽可能多的逻辑移动到视图中。 Your VB.NET code could call the view and present the data in a more elegant data table format rather than returning a simple flat file (assuming that this is intended to present data to humans for analysis rather than producing files in a particular format that are fed into some downstream process).您的 VB.NET 代码可以调用视图并以更优雅的数据表格式呈现数据,而不是返回简单的平面文件(假设这旨在将数据呈现给人类进行分析,而不是生成特定格式的文件,然后输入一些下游过程)。 That would be more effort than invoking SQL*Plus but would mean that your upgrade of the legacy system would produce much more user-friendly results.这将比调用SQL*Plus更费力,但意味着您对旧系统的升级将产生对用户更友好的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM