【问题标题】:How to execute an Oracle .SQL script file using asp.net (vb.net)如何使用 asp.net (vb.net) 执行 Oracle .SQL 脚本文件
【发布时间】:2021-03-14 20:18:53
【问题描述】:

我在这里尝试做的总体目标是从 asp.net (vb.net) Web 应用程序中执行 Oracle SQL 脚本,其中包含 SQL*Plus 命令,用于查询数据并将结果放到一个文本文件,然后将文本文件显示给 Web 应用程序的最终用户。我在尝试在我的 Visual Studio 代码中执行 .sql 文件时遇到问题,它告诉我它不是有效的 SQL 语句。当然这是有道理的,因为 .sql 文件中的内容比 sql 语句要多。

我在我的 Visual Studio 项目中使用 .NET 版本 4.6.1,我正在调用 Oracle 11 数据库。

这是我要执行的代码。当它到达尝试执行脚本的行时,它会抛出以下错误:

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

这是 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

.sql 文件对 Oracle 进行几次调用,然后将结果导出(假脱机)到 .txt 文件。执行 .sql 脚本后,我将显示在浏览器中创建的 .txt 文件。

我在下面提供了 .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

【问题讨论】:

  • p_sum.sql 中有什么?例如,除了 SQL 之外,是否还有 SQL*Plus 命令?
  • 我现在已经在我的问题陈述中包含了上述 .sql 文件的副本,但是是的,.sql 文件中包含 SQL*Plus 推荐以及 SQL 语句。

标签: sql .net oracle


【解决方案1】:

不幸的是,您的 VB.NET 代码不知道如何处理嵌入在脚本中的所有 SQL*Plus 命令。 SQL*Plus 是唯一支持全套命令的应用程序。 SQL Developer 支持SQL*Plus 命令的子集。看起来 SQL Developer 将支持此特定脚本中的所有 SQL*Plus 命令,但我需要阅读文档才能确定。

快速而肮脏的解决方案是从 VB 到操作系统并调用 SQL*Plus 来生成文件,然后让 VB.NET 将文件返回给客户端。这不是特别优雅,并且在多用户环境中会遇到问题,因为如果使用相同的参数调用脚本,它将尝试从两个不同的会话中假脱机相同的文件。但似乎旧版解决方案已经存在相同的多用户问题。

更优雅的解决方案是重构脚本以将尽可能多的逻辑移动到视图中。您的 VB.NET 代码可以调用视图并以更优雅的数据表格式呈现数据,而不是返回简单的平面文件(假设这是为了将数据呈现给人类进行分析,而不是生成特定格式的文件)送入一些下游过程)。这将比调用 SQL*Plus 更费力,但意味着您对旧系统的升级会产生对用户更友好的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    • 2020-09-28
    • 2011-01-05
    • 2014-10-28
    相关资源
    最近更新 更多