将T-SQL函数转换为PL / SQL

时间:2011-11-18 09:44:55

标签: sql-server oracle

  

可能重复:
  How to best split csv strings in oracle 9i

你能帮我把以下T-SQL功能转换成Oracle吗?该函数转换类似

的字符串
service|nvretail;language|de;yyyy|2011;

到桌子。

我遇到的主要问题是使用临时表。我在Oracle中找不到任何相同的东西。

CREATE FUNCTION [dbo].[TF_ConvertPara]
(   
  @parastringNVARCHAR(max)
)
RETURNS @para TABLE 
(
  [Key]    varchar(max),
  [Value]  varchar(max)
)
begin
  DECLARE @NextString NVARCHAR(40)
  DECLARE @Pos1       INT
  DECLARE @Pos2       INT
  DECLARE @NextPos    INT
  DECLARE @Delimiter1 NCHAR=';'
  DECLARE @Delimiter2 NCHAR='|'

  if substring(@paraString, len(@paraString) - 1, 1) <> @Delimiter1
    SET @paraString = @paraString + @Delimiter1

  SET @Pos1 = charindex(@Delimiter1, @paraString)
  WHILE (@pos1 <> 0)
  BEGIN
    SET @NextString = substring(@paraString, 1, @Pos1 - 1)
    SET @paraString = substring(@paraString, @pos1 + 1, len(@paraString))
    SET @pos1 = charindex(@Delimiter1, @paraString)

    SET @Pos2 = charindex(@Delimiter2, @NextString)
    if (@Pos2 > 0)
    begin
      insert into @para 
        values
      (substring(@NextString, 1, @Pos2 - 1),
       substring(@NextString, @Pos2 + 1, len(@NextString)))
    end
  END 
  return;
end  

提前谢谢。

2 个答案:

答案 0 :(得分:3)

如果您希望将字符串的标记作为行返回,那么您可以在单个SQL查询中完成所有操作:

WITH t AS (SELECT 'service|nvretail;language|de;yyyy|2011;' as val FROM dual)
SELECT row_output
  FROM t,
       XMLTABLE( '/root/e/text()'
          PASSING xmltype( '<root><e>' || 
                            REGEXP_REPLACE (t.val, '(;|\|)', '</e><e>' ) || 
                           '</e></root>' )
                  COLUMNS row_output VARCHAR2( 4000 ) PATH '/');

返回:

service 
nvretail
language
de      
yyyy    
2011

如果你想在表中包含这些行,那么将SQL包装在一个简单的函数中,以返回内存中的表或将记录插入到数据库表中,无论你需要什么。

以下是返回VARCHAR2记录的表(集合)的函数示例:

CREATE OR REPLACE
FUNCTION str_to_table (
   p_input_str IN VARCHAR2
)
RETURN DBMS_SQL.VARCHAR2_TABLE
IS
   CURSOR str_to_rows (
      cp_str IN VARCHAR2
   )
   IS
      SELECT row_output
        FROM (SELECT cp_str as val FROM dual) t,
             XMLTABLE( '/root/e/text()'
                PASSING xmltype( '<root><e>' || 
                        REGEXP_REPLACE(t.val, '(;|\|)', '</e><e>') || 
                                 '</e></root>' )
                        COLUMNS row_output VARCHAR2( 4000 ) PATH '/');

   varchar_tab DBMS_SQL.VARCHAR2_TABLE;
BEGIN
   OPEN  str_to_rows(p_input_str);
   FETCH str_to_rows BULK COLLECT INTO varchar_tab;
   CLOSE str_to_rows;
   --
   RETURN varchar_tab;
EXCEPTION
   WHEN others
   THEN
      IF str_to_rows%ISOPEN
      THEN
         CLOSE str_to_rows;
      END IF;
      RAISE;
END str_to_table;

它未经测试,因此可能存在一些语法错误,但它应该是prety close。

返回引用光标:

CREATE OR REPLACE
FUNCTION str_to_table (
   p_input_str IN VARCHAR2
)
RETURN sys_refcursor
IS                       
   cur SYS_REFCURSOR;
BEGIN
   OPEN cur
    FOR SELECT row_output
          FROM (SELECT p_input_str as val FROM dual) t,
               XMLTABLE( '/root/e/text()'
                         PASSING xmltype( '<root><e>' || 
                         REGEXP_REPLACE (t.val, '(;|\|)', '</e><e>' ) || 
                                          '</e></root>' )
                         COLUMNS row_output VARCHAR2( 4000 ) PATH '/');
   --
   RETURN cur;
END str_to_table;

希望它有所帮助...

答案 1 :(得分:2)

要返回键值对,如何(对于Oracle 10g及更高版本):

CREATE OR REPLACE FUNCTION csv_to_rows(mycsv IN VARCHAR2)
RETURN sys_refcursor
AS
  c SYS_REFCURSOR;
BEGIN
    OPEN c FOR         
        SELECT SUBSTR(element,1,INSTR(element,'|')-1) as key ,
        SUBSTR(element,INSTR(element,'|')+1,99999) as val
        FROM (
            SELECT REGEXP_SUBSTR(mycsv,'[^;]+',1,LEVEL) element          
                FROM dual      
                CONNECT BY LEVEL < LENGTH(REGEXP_REPLACE(mycsv,'[^;]+')) + 1
             );
    RETURN c;     
END;

并查看结果:

DECLARE 
    c SYS_REFCURSOR;
    akey VARCHAR2(100);
    aval VARCHAR2(100);
BEGIN
 c := csv_to_rows('service|nvretail;language|de;yyyy|2011');
 LOOP
     FETCH c into akey,aval;
     EXIT WHEN c%NOTFOUND;

     dbms_output.put_line('Key : '||akey || ' Value : '||aval);
 END LOOP;    
END;

这应该给你

Key : service  Value : nvretail
Key : language Value : de
Key : yyyy     Value : 2011