【问题标题】:Convert a PL/SQL Stored Procedure in Oracle to Transact-SQL for SQL Server将 Oracle 中的 PL/SQL 存储过程转换为 SQL Server 的 Transact-SQL
【发布时间】:2014-11-01 08:30:55
【问题描述】:

我有一个用 PL/SQL 编写的存储过程,用于在 Oracle 中执行:

CREATE OR REPLACE PROCEDURE  "ZSPLKIMGR" 
  (
    businessArea       IN TYPES.CHAR10,
    memberNumber       IN TYPES.CHAR35,
    P_CURSOR           IN OUT TYPES.GENCURSOR )
                       IS
BEGIN
  OPEN P_CURSOR FOR

  SELECT W03.* , BE.* FROM BEIMGR BE
  LEFT JOIN W03U999S W03 ON (BE.CRDATTIM = W03.CRDATTIM AND BE.RECORDCD = W03.RECORDCD AND BE.CRNODE = W03.CRNODE) 
  WHERE ( UPPER(W03.UNITCD) = UPPER(businessArea)  OR UPPER(businessArea)   = ''  OR UPPER(businessArea)  IS NULL ) 
  AND ( UPPER(BE.MEMN) = UPPER(memberNumber)       OR UPPER(memberNumber)      = ''  OR UPPER(memberNumber)   IS NULL);                                        
END;

这个存储过程正在返回一个游标,当我从 SOAPUI 进行查找时,它给了我预期的结果。

我将此存储过程转换为 Transact-SQL for SQL Server 如下所示:

ALTER PROCEDURE  [dbo].[ZSPLKIMGR]  
    @businessArea   CHAR(10),
    @memberNumber   CHAR(35),
    @P_CURSOR       CURSOR VARYING OUTPUT
AS
  SET NOCOUNT ON;
  SET @P_CURSOR = CURSOR FORWARD_ONLY STATIC FOR
      SELECT W03.* , PQ.* 
      FROM PQCUSTSRV PQ
      LEFT JOIN W03U999S W03 ON (PQ.CRDATTIM = W03.CRDATTIM AND PQ.RECORDCD = W03.RECORDCD AND PQ.CRNODE = W03.CRNODE) 
      WHERE (UPPER(W03.UNITCD) = UPPER(@businessArea) 
             OR UPPER(@businessArea) = ''  
             OR UPPER(@businessArea) IS NULL) 
        AND (UPPER(PQ.FOLDERID) = UPPER(@memberNumber)     
             OR UPPER(@memberNumber) = ''  
             OR UPPER(@memberNumber) IS NULL); 

  OPEN  @P_CURSOR;       

当我执行这个存储过程时,它在 SOAPUI 中显示错误 -

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <soapenv:Fault>
         <faultcode>soapenv:Server</faultcode>
         <faultstring>Error while processing the Web service request, please contact admin.</faultstring>
         <faultactor>XML Server</faultactor>
      </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>

任何人都可以将 PL/SQL SP 转换为 Transact/SQL 吗?

我还尝试从 SQL Server Management Studio 执行存储过程,手动提供输入参数,但它显示错误

操作数类型冲突:int 与光标不兼容

注意 - 请忽略两个存储过程中使用的不同表 PQCUSTSRV、BEIMGR。

【问题讨论】:

  • 查看官方DECLARE CURSOR 声明。您是否有特殊原因需要将光标放在变量中?
  • @Josien 是的,要求就像SP应该以游标的形式返回结果。
  • 为什么需要光标?请执行 SOAP 层,以便可以看到是否需要游标。 (SQL Server 和 Oracle 的情况可能完全不同)

标签: sql-server oracle tsql stored-procedures plsql


【解决方案1】:

此外,如果您的数据不区分大小写,则根本不需要使用UPPER() 函数来比较两个字符串,这会对性能产生影响。因为 SQL Server 必须触摸表中的每一行以将其转换为大写第 1 行,然后将其与传递的变量进行比较。

假设这是区分大小写的,我已将此功能保留在下面的解决方案中。

ALTER PROCEDURE  [dbo].[ZSPLKIMGR]  
   @businessArea   CHAR(10),
   @memberNumber   CHAR(35)
AS
BEGIN
  SET NOCOUNT ON;

  SELECT W03.* , PQ.* 
  FROM PQCUSTSRV PQ
  LEFT JOIN W03U999S W03 ON PQ.CRDATTIM = W03.CRDATTIM 
    AND PQ.RECORDCD = W03.RECORDCD AND PQ.CRNODE = W03.CRNODE
    AND ( UPPER(W03.UNITCD) = UPPER(@businessArea)  
                               OR @businessArea = ''  OR @businessAre IS NULL ) 
    AND ( UPPER(PQ.FOLDERID) = UPPER(@memberNumber) 
                               OR @memberNumber = ''  OR @memberNumber IS NULL)
END

【讨论】:

  • 没有游标,你也不需要一个,在 SQL Server 中游标应该是你最后的选择,SQL Server 在基于集合的操作上工作得更好。尝试上面的代码,它会带来相同的结果。
【解决方案2】:

感谢 M.Ali 的帖子。 您的代码在进行一些更改后运行良好。关注这个-

ALTER PROCEDURE  [dbo].[ZSPLKIMGR]  
   @businessArea   CHAR(10),
   @memberNumber   CHAR(35)
AS
BEGIN
  SET NOCOUNT ON;

  SELECT W03.* , PQ.* 
  FROM PQCUSTSRV PQ
 LEFT JOIN W03U999S W03 ON (PQ.CRDATTIM = W03.CRDATTIM AND PQ.RECORDCD = W03.RECORDCD AND PQ.CRNODE = W03.CRNODE) 
      WHERE (UPPER(W03.UNITCD) = UPPER(@businessArea) 
             OR UPPER(@businessArea) = ''  
             OR UPPER(@businessArea) IS NULL) 
        AND (UPPER(PQ.FOLDERID) = UPPER(@memberNumber)     
             OR UPPER(@memberNumber) = ''  
             OR UPPER(@memberNumber) IS NULL)
END

【讨论】:

  • 这个 where 子句会将这个 LEFT JOIN 转换成一个 INNER JOIN
猜你喜欢
  • 2018-05-06
  • 1970-01-01
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
  • 2017-06-03
  • 2014-08-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多