0

我有一个逗号分隔的字符串列表(来自用户输入),我想将此列表用作嵌套 sql 块中的 pl/sql 存储函数中的参数,使用“not in where 子句”。

我找不到一种优雅的方式让它工作......

这就是我的想法:

CREATE TABLE example ( somevalue VARCHAR(36) NOT NULL);
--
INSERT INTO example VALUES ('value1');
INSERT INTO example VALUES ('value2');
INSERT INTO example VALUES ('value3');
--
SELECT * FROM example;
--
CREATE OR REPLACE
  FUNCTION resultmaker(
      ignoreList IN VARCHAR2)
    RETURN VARCHAR2
  IS
    result VARCHAR2(4000);
  BEGIN
    result  := 'Here is my calculated result, using ignorelist=' || ignoreList || ':'     || CHR(10);
    FOR rec IN
    (SELECT DISTINCT somevalue
    FROM example
    WHERE somevalue NOT IN resultmaker.ignoreList -- here's my issue, the NOT IN     clause using the parameter value
    )
    LOOP
      result := result || 'not in ignorelist: ' || rec.somevalue || CHR(10);
    END LOOP;
    result := result || '.' || CHR(10);
    --
    RETURN result;
  END resultmaker;
  /
--
-- simulate function call with user input 'value2, value3'
SELECT resultmaker('value2, value3') FROM dual; -- doesn't work  
--
DROP TABLE example;
DROP FUNCTION resultmaker;
4

5 回答 5

1

只需传递参数 like'"value2","value3"'并让您的语句将双引号替换为单引号 like REPLACE(@Param1,'"','''')

调用函数: SELECT * FROM Function1('"value2","value3"')

内部功能: NOT IN REPLACE(@Param1,'"','''')

于 2015-10-14T15:39:59.150 回答
0

这是我对上面的原始问题使用动态 sql 的解决方案:

CREATE TABLE example ( somevalue VARCHAR(36) NOT NULL);
--
INSERT INTO example VALUES ('value1');
INSERT INTO example VALUES ('value2');
INSERT INTO example VALUES ('value3');
--
SELECT * FROM example;
--
CREATE OR REPLACE
  FUNCTION resultmaker(
      ignoreList IN VARCHAR2)
    RETURN VARCHAR2
  IS
    result VARCHAR2(4000);
    example_cursor sys_refcursor;
    rec example.somevalue%type;
  BEGIN
    result := 'Here is my calculated result, using ignorelist=' || ignoreList || ':' || CHR(10);
    OPEN example_cursor FOR ( 'SELECT DISTINCT somevalue FROM example WHERE somevalue NOT IN (' || ignoreList || ')' );
    FETCH example_cursor INTO rec;
    WHILE example_cursor%found
    LOOP
      result := result || 'not in ignorelist: ' || rec || CHR(10);
      FETCH example_cursor INTO rec;
    END LOOP;
    CLOSE example_cursor;
    result := result || '.' || CHR(10);
    --
    RETURN result;
  END resultmaker; 
/
--
-- simulate function call with user input 'value2', 'value3'
SELECT resultmaker('''value2'', ''value3''') FROM dual;
--
DROP TABLE example;
DROP FUNCTION resultmaker;
于 2013-01-04T15:10:38.857 回答
0

经典且可能正确的解决方案是使用 PL/SQL 表将其作为参数传递...

于 2013-01-04T21:29:59.693 回答
0

在每种情况下,您都应该解析该输入。由于 PL/SQL 中没有内置的字符串标记器(至少我找不到它)您可能想查看这些选项,

http://blog.tanelpoder.com/2007/06/20/my-version-of-sql-string-to-table-tokenizer/

PL/SQL 是否有与 Java 等效的 StringTokenizer?

解析字符串后,您可以创建一个新字符串,如:

not_in_statement varchar2(1000);
CURSOR c1 IS select token from tokenized_strings_table;
BEGIN
    not_in_statement := '('
    FOR rec IN c1 LOOP
        not_in_statement := not_in_statement || '''||rec.token||'''||','
    END LOOP
    not_in_statement := not_in_statement||')'
END

SELECT DISTINCT somevalue
FROM example
WHERE somevalue NOT IN not_in_statement

您可能需要将其设为动态 SQL,我没有时间尝试。

于 2013-01-04T13:23:08.963 回答
0

asktom.oracle.com 上有一些很好的解决方案,用于获取一串值并为它们动态创建 IN 子句:

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:210612357425

于 2013-01-05T05:18:48.583 回答