使用字符串引用问题pl sql提取字符串

时间:2015-01-26 10:54:20

标签: sql oracle function plsql quote

我使用下面的函数从输入中的字符串中提取字符串,问题是当我把字符串字符与字符串引用时我无法提取它 exp作为输入:

AA015streetl'adeuilAB00201AC0041234AD012XXXXXXXXXXXXAE009TTTTTTTTT

FUNCTION get_string (p_name    IN               VARCHAR2,
                     p_strg    IN               VARCHAR2,
                     p_len    OUT NOCOPY        PLS_INTEGER,
                     p_value  OUT NOCOPY        VARCHAR2)
        RETURN PLS_INTEGER
    IS
        v_counter   PLS_INTEGER := 1;
        v_strg       VARCHAR2 (4096) := SUBSTR (p_strg, 5);
    BEGIN
        p_value := NULL;
        p_len := 0.;

        WHILE v_counter < LENGTH (v_strg)
        LOOP
            IF SUBSTR (v_strg, v_counter, 3.) = p_name
            THEN
                p_len :=
                    TO_NUMBER (SUBSTR (v_strg, v_counter + 3., 3.));
                p_value :=
                    SUBSTR (v_strg, v_counter + 6., p_len);
                RETURN (declaration_cst.ok);
            END IF;

            v_counter :=
                  v_counter
                + 6.
                + TO_NUMBER (SUBSTR (v_strg, v_counter + 3., 3.));
        END LOOP;

        RETURN (declaration_cst.nok);
            END;
    END get_string;

2 个答案:

答案 0 :(得分:3)

对于您显示的示例字符串,代码中的子字符串偏移和计数器调整已关闭。这可以提取任何“标签”:

CREATE OR REPLACE FUNCTION get_string (p_name IN VARCHAR2, p_strg IN VARCHAR2,
    p_len OUT NOCOPY PLS_INTEGER, p_value OUT NOCOPY VARCHAR2)
RETURN PLS_INTEGER IS
    v_counter PLS_INTEGER := 1;
BEGIN
    p_value := NULL;
    p_len := 0;

    WHILE v_counter < LENGTH (p_strg)
    LOOP
        IF SUBSTR (p_strg, v_counter, 2) = p_name
        THEN
            p_len := TO_NUMBER (SUBSTR (p_strg, v_counter + 2, 3));
            p_value := SUBSTR (p_strg, v_counter + 5, p_len);
            RETURN declaration_cst.ok;
        END IF;

        v_counter := v_counter + 5
            + TO_NUMBER (SUBSTR (p_strg, v_counter + 2, 3));
    END LOOP;

    RETURN declaration_cst.nok;
END get_string;
/

您的版本在v_strg作业中完全丢失了前四个字符,然后进行调整,好像标记是三个字符,而不是两个字符。

使用类似的测试块:

set serveroutput on size unlimited
declare
  str varchar2(256) := q'[AA015street l'adeuilAB00201AC0041234AD012XXXXXXXXXXXXAE009TTTTTTTTT]';
  len pls_integer;
  value varchar2(256);
  rc pls_integer;
begin
  rc := get_string('AB', str, len, value);
  dbms_output.put_line('AB -> ' || rc ||':'|| len ||':'|| value);
end;
/

并更改“AB”标记:

AA -> 0:15:street l'adeuil
AB -> 0:2:01
AC -> 0:4:1234
AD -> 0:12:XXXXXXXXXXXX
AE -> 0:9:TTTTTTTTT
AF -> 1:0:
带有包装函数的

SQL Fiddle demo,因此可以更轻松地显示提取的标签信息。

如果字符串值包含单引号,则没有任何区别,只要标记长度正确 - 它只是substr的另一个字符,并且不会以任何不同的方式进行解释。

正如Bob Jarvis所说,还有其他方法可以实现这一细分,但这甚至超出了你所要求的范围。

答案 1 :(得分:2)

当您在字符串文字中嵌入单引号时,您试图传递给函数或过程,您需要将其加倍(即键入两个单引号而不是一个),以便PL / SQL正确解释它。如你想要的那样,doubled单引号将作为一个单引号发送给函数,但这就是在PL / SQL中处理文字中单引号的方式。因此,而不是将您的函数称为

n := get_string ('AB', 
                 'AA015streetl'adeuilAB00201AC0041234AD012XXXXXXXXXXXXAE009TTTTTTTTT', 
                 p_len,
                 p_value );

你应该在第二个参数中加倍单引号:

n := get_string ('AB', 
                 'AA015streetl''adeuilAB00201AC0041234AD012XXXXXXXXXXXXAE009TTTTTTTTT', 
                 p_len,
                 p_value );

如果您正在阅读文件或其他外部来源的输入,则您不必这样做;仅当字符串 literal 中包含单引号时才需要它。

分享并享受。