1

我正在使用 Oracle 的 ADO.Net 提供程序来执行 2 个用分号分隔的选择语句。我正在使用 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)
4

2 回答 2

2

您通常不能在一次调用中运行多个 SQL 语句,而且切换到 PL/SQL 并不是真正必要的。看起来您正在尝试同时计算匹配行的数量,我想您可以执行类似“30 的结果 1 到 5”之类的操作。虽然您可以进行两次单独的调用,但由于另一个事务可能在两者之间提交,它们可能会得到不一致的结果(因此您不希望 '25 to 30 of 29' 或部分最后一页,如 '25 to 29 of 30'?)。

您可以在每个返回的行中将总计数作为一个额外的字段,这有点多余但不会再花费 - 实际上更少,因为您只打了一次表,您没有两个单独的查询。这使用 , 的analytic function版本count和一个空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在内部查询中添加一个子句,或者将其更改RowNumROW_NUMBER() OVER(ORDER BY Contract_ID)坚持分析主题。


不太确定你想从你的评论中得到什么。如果您想要匹配 each 的记录数Contract_Id,您可以在内部查询中添加另一个术语:

    COUNT(1) OVER (PARTITION BY Contract_Id) Contract_Id_Count

如果您想要不同值的总数Contract_Id,请改为添加:

    COUNT(DISTINCT Contract_Id) OVER () Contract_Id_Count
于 2012-07-30T10:46:33.020 回答
1

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

我目前认为解决瘦问题的唯一方法是使用存储过程(不如 T-SQL 好或易于编码),但它确实允许执行批处理语句。

于 2012-08-01T15:43:41.303 回答