Oracle中2个SELECT语句之间的分号会导致System.Data.OracleClient出错

时间:2012-07-28 18:57:47

标签: oracle ado.net

我正在使用Oracle的ADO.Net提供程序来执行由分号分隔的2个select语句。我正在使用system.Data.OracleClient数据提供程序。但是,似乎Oracle不喜欢分号,因为当ADO.Net代码运行时,我得到一个无效的字符错误。有关如何解决这个问题的任何想法,因为我必须在相同的数据库行程中运行两个SELECT语句?

            string sql = @"
                        WITH
                      x AS
                      (
                        SELECT
                          RowNum AS RowIndex,
                          CAST(Contract_Id AS VARCHAR2(1000)) Contract_Id,
                          Contract_Number,
                          Name AS Contract_Name,
                          Contract_Number
                          || ' '
                          || Name AS Contract_Description,
                          Eff_Date,
                          Expiry_Date
                        FROM
                         contracts
                        WHERE
                          contract_number LIKE :ContractSearchText
                        OR name LIKE :ContractSearchText
                      )
                    SELECT
                      *
                    FROM
                      x
                    WHERE
                      RowIndex  >= :StartingRowIndex
                    AND RowIndex < (:StartingRowIndex + :MaxRows) ;

                    SELECT
                          COUNT(*)
                        FROM
                          contracts
                        WHERE
                          contract_number LIKE :ContractSearchText
                        OR name LIKE :ContractSearchText;
                       ";

更新

亚历克斯的回复是我能找到的最佳答案。但是,我提出了另一个替代答案,我不确定该表是被击中两次还是只有一次。备用查询依赖于使用计数派生表创建CROSS JOIN。可能有人可以告诉我,在这个替代答案中该表只被击中一次吗?

                          WITH
                      x AS
                      (
                        SELECT
                          RowNum AS RowIndex,
                          CAST(Contract_Id AS VARCHAR2(1000)) Contract_Id,
                          Contract_Number,
                          Name AS Contract_Name,
                          Contract_Number
                          || ' '
                          || Name AS Contract_Description,
                          Eff_Date,
                          Expiry_Date
                        FROM
                          vha_int_contract
                        WHERE
                          contract_number LIKE :ContractSearchText
                        OR name LIKE :ContractSearchText
                      ),
                      y as ( select count(distinct contract_id)  TotalCount from x)
                    SELECT
                      *
                    FROM
                      x cross join y
                    WHERE
                      RowIndex  >= :StartingRowIndex
                    AND RowIndex < (:StartingRowIndex + :MaxRows)

2 个答案:

答案 0 :(得分:2)

通常不能在调用中运行多个SQL语句,并且不一定需要切换到PL / SQL。看起来你正试图在同一时刻计算匹配行的数量,我想你可以做一些类似'结果1到5的30'的事情。虽然你可以做两个单独的调用,但是他们可能会得到不一致的结果,因为另一个事务可以在它们之间提交(所以你不需要'25到30的29',或者部分的最后一页像'25到29 30' ?)。

您可以将总计数作为每个返回行中的额外字段,这有点多余,但不会花费更多 - 实际上更少,因为您只打了一次表,没有两个单独的查询。这使用analytic function count版本的{{3}},并带有一个空的over子句,因为在这种情况下你想要计算所有内容:

SELECT x.*, COUNT(1) OVER () Range_Count
FROM
(
    SELECT
        RowNum AS RowIndex,
        CAST(Contract_Id AS VARCHAR2(1000)) Contract_Id,
        Contract_Number,
        Name AS Contract_Name,
        Contract_Number
        || ' '
        || Name AS Contract_Description,
        Eff_Date,
        Expiry_Date,
        COUNT(1) OVER () Total_Count
    FROM
        contracts
    WHERE
        contract_number LIKE :ContractSearchText
        OR name LIKE :ContractSearchText
    ) x
WHERE RowIndex >= :StartingRowIndex
AND RowIndex < (:StartingRowIndex + :MaxRows)

我在这里做了两件事,只是为了好玩。您需要的是内部查询COUNT(1) OVER () Total_Count;这会在返回的每一行上为您提供Total_Count列,其值等于原始单独的COUNT(*)查询所找到的值。我已经在外部查询上添加了一个COUNT(1) OVER () Range_Count,它将显示该范围内有多少条记录 - 在您到达最后一页'页面'之前将是:Max_Rows。可能没有用,您可以在处理行时对行进行计数,但只是真的可以显示它们。

您目前在查询中没有任何排序,这意味着您可能无法获得预期的结果。我建议你在内部查询中添加ORDER BY子句,或者将RowNum更改为ROW_NUMBER() OVER(ORDER BY Contract_ID)以坚持分析主题。


不完全确定你的意见是什么。如果您想要与每个Contract_Id匹配的记录数,可以在内部查询中添加另一个术语:

    COUNT(1) OVER (PARTITION BY Contract_Id) Contract_Id_Count

如果您想要不同Contract_Id值的总数,请添加以下内容:

    COUNT(DISTINCT Contract_Id) OVER () Contract_Id_Count

答案 1 :(得分:1)

除了能够为操作提供更好的方法之外,我们是否可以说ado.net不喜欢分号?我运行一些批量查询,通常是一个创建表,做一些事情,然后删除表。 在T-SQL中,上述情况是可能的,因为SQL Server不需要使用分号来终止大多数操作中的语句,这与终结者必须使用的Oracle不同。

我目前唯一可以考虑解决瘦问题的方法是使用存储过程(不像T-SQL那样好或容易编码),但它确实允许执行批处理语句。