【问题标题】:How to convert MS SQL Stored Procedure to Oracle如何将 MS SQL 存储过程转换为 Oracle
【发布时间】:2015-07-05 12:16:39
【问题描述】:

我被这个查询卡住了。我尝试转换,但我是 Oracle 11 g 的新手。

这是用 Oracle 11 g 转换的 ms sql 存储过程。

CREATE PROCEDURE [dbo].[GetCustomers_Pager]
       @SearchTerm VARCHAR(100) = ''
      ,@PageIndex INT = 1
      ,@PageSize INT = 10
      ,@RecordCount INT OUTPUT
AS
BEGIN
      SET NOCOUNT ON;
      SELECT ROW_NUMBER() OVER
      (
            ORDER BY [CustomerID] ASC
      )AS RowNumber
      ,[CustomerID]
      ,[CompanyName]
      ,[ContactName]
      ,[City]
      INTO #Results
      FROM [Customers]
      WHERE [ContactName] LIKE @SearchTerm + '%' OR @SearchTerm = ''
      SELECT @RecordCount = COUNT(*)
      FROM #Results

      SELECT * FROM #Results
      WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1

      DROP TABLE #Results
END

我发现这个ms sql存储过程到this link

这是我失败的 oracle 存储过程。我坚持使用 INTO 语法。

CREATE OR REPLACE
PROCEDURE GetCustomers_Pager
( SearchTerm IN VARCHAR2
, PageIndex IN NUMBER DEFAULT 1
, PageSize IN NUMBER DEFAULT 10
, RecordCount OUT NUMBER
) AS
BEGIN  
  SELECT  
          ROW_NUMBER() OVER( ORDER BY CustomerID ASC )AS RowNumber,
          ,CustomerID
          ,CompanyName
          ,ContactName
          ,City
  INTO Results
  FROM Customers
  WHERE ( Customers LIKE SearchTerm + '%' OR ContactName LIKE SearchTerm + '%') OR SearchTerm = '';
  SELECT RecordCount = COUNT(*)
  FROM Results;
  SELECT * FROM Results
  WHERE RowNumber BETWEEN(PageIndex -1) * PageSize + 1 AND(((PageIndex -1) * PageSize + 1) + PageSize) - 1;
  DROP TABLE Results;

END GetCustomers_Pager;

谁能帮帮我?

【问题讨论】:

  • 你使用什么oracle版本? perhaps this may help.
  • 首先要做的是删除[..]“引号”。这些对于 SQL 标识符无效。
  • 我认为原始 SQLServer 过程没有任何意义。似乎是这样做的: 1) 将与联系人姓名匹配的Customers 表中的一堆数据插入到临时表#Results 中。 2) 获取#Results 的行数到OUT 参数RecordCount。 3) 对Results 表执行一个模仿分页的冗余查询。分页结果集不在任何地方使用。 4)DROPs 表#Results。除非发生了一些隐藏的 SQLServer 魔法,否则我认为可以使用单个 COUNTCustomers 表来完成同样的事情。
  • 根据您粘贴的过程,您在 SELECT ROW_NUMBER() OVER( ORDER BY CustomerID ASC )AS RowNumber, 处有 2 个逗号,然后 into 子句必须具有与 select 语句中相同数量的参数
  • @MickMnemonic:确实发生了一些“魔术”,该过程将(隐式)返回最后一个 select 语句的结果 - 这就是 Oracle 12c 引入“隐式结果集”的原因,但这在 11g 中不可用。我认为唯一的选择是使用返回结果集的流水线函数,然后从该函数中进行选择。

标签: sql sql-server oracle sql-server-2008 stored-procedures


【解决方案1】:

您只能在SELECT INTO 子句中使用简单类型变量,用于选择数组使用SELECT BULK COLLECT INTO。但是你必须声明你选择的变量并且它的类型必须匹配。

如果您只想选择计数,请使用:

SELECT COUNT(*) INTO RecordCount
FROM (SELECT ROW_NUMBER() OVER( ORDER BY CustomerID ASC )AS RowNumber,
             CustomerID,
             CompanyName,
             ContactName,
             City
     FROM Customers
     WHERE ( Customers LIKE SearchTerm + '%' OR ContactName LIKE SearchTerm + '%') OR SearchTerm = '') s
WHERE RowNumber BETWEEN (PageIndex-1)*PageSize + 1 AND PageIndex*PageSize;

如果要返回记录,则必须定义数组类型,添加输出参数Records并使用SELECT * BULK COLLECT INTO Records,然后使用RecordCount := Records.COUNT;

但返回数据的首选方式是REF CURSOR 输出参数,请参阅http://oracle-base.com/articles/misc/using-ref-cursors-to-return-recordsets.php

【讨论】:

    【解决方案2】:

    以光标为输出参数的Oracle过程代码:

    CREATE OR REPLACE PROCEDURE GetCustomers_Pager (
      SearchTerm IN VARCHAR2, PageIndex IN NUMBER DEFAULT 1, PageSize IN NUMBER DEFAULT 10, 
      RecordCount OUT NUMBER, Records out sys_refcursor ) AS
    
    begin
      -- count all matching rows
      select count(1) into RecordCount from Customers
        where ContactName like SearchTerm||'%';
    
      -- get all matching rows into cursor "Records"
      -- and filter them including PageIndex and PageSize parameters
      open Records for 
      select rn, customerid, companyName, contactName, City 
        from (
          select row_number() over (order by customerID) rn,
              customerid, companyName, contactName, City
            from customers where ContactName like SearchTerm||'%' )
        where rn between (PageIndex-1) * PageSize
          and (((PageIndex-1) * PageSize + 1) + PageSize) - 1;
    end GetCustomers_Pager;
    

    调用此过程并填充 DataGridView 的示例 C# 代码:

    OracleCommand cmd = new OracleCommand();
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText = "getcustomers_pager";
    cmd.Connection = CONNECTION.oconn;
    cmd.Parameters.Add(new OracleParameter("SearchTerm", OracleType.VarChar, 3)).Value = "Mar";
    cmd.Parameters.Add(new OracleParameter("PageIndex", OracleType.Number)).Value = 1;
    cmd.Parameters.Add(new OracleParameter("PageSize", OracleType.Number)).Value = 5;
    OracleParameter p = new OracleParameter("RecordCount", OracleType.Number);
    p.Direction = ParameterDirection.Output;
    cmd.Parameters.Add(p);
    p = new OracleParameter("Records", OracleType.Cursor);
    p.Direction = ParameterDirection.Output;
    cmd.Parameters.Add(p);
    
    OracleDataAdapter da = new OracleDataAdapter();
    da.SelectCommand = cmd;
    DataSet ds = new DataSet();
    da.Fill(ds);
    
    dgv.DataSource = ds.Tables[0];
    

    【讨论】:

    • 我创建了 oracle 存储过程,但我使用的是 Ole DB dll。我如何使用 Oracle dll?有什么建议吗?咳咳……
    • 据我所知,您应该将OracleCommand 替换为OracleDBCommand,将OracleType 替换为OracleDBType 等,看看Intellisense 的建议。不确定,但这应该可以,只是谷歌的例子。
    • OracleType.Cursor 不支持 Ole Db。可能我可以使用 oracle 数据访问 dll。感谢您的帮助。
    猜你喜欢
    • 2020-10-12
    • 2013-10-10
    • 2021-08-17
    • 1970-01-01
    • 2018-05-06
    • 2013-12-18
    • 1970-01-01
    • 2020-09-28
    • 2019-10-19
    相关资源
    最近更新 更多