在 Oracle PL_SQL 函数中将列名作为参数传递

Passing column name as parameter in Oracle PL_SQL function

我正在尝试传递两个输入参数,列名和 table 名称。然后该函数应输出如下定义的字符串值:

create or replace function get_id5(in_col_name IN VARCHAR2,in_tbl_name IN VARCHAR2)
  return VARCHAR2
is
  /*in_col_nm varchar(32) := in_col_name;
  /*in_tbl_nm varchar(64) := in_tbl_name; */
  integer_part  NUMBER ;
  integer_part_str VARCHAR2(32) ;
  string_part VARCHAR2(32) ;
  full_id VARCHAR2(32) ;
  out_id VARCHAR(32) ;

BEGIN
/*select MAX(in_col_nm) INTO full_id FROM  in_tbl_nm ;  */
execute immediate 'select MAX('||in_col_name||') FROM' || in_tbl_name ||'INTO' || full_id;
/*select regexp_replace(full_id , '[^0-9]', '') INTO integer_part_str  , regexp_replace(full_id , '[^a-z and ^A-Z]', '') INTO string_part from dual ; */
integer_part_str := regexp_replace(full_id , '[^0-9]', '') ;
string_part := regexp_replace(full_id , '[^a-z and ^A-Z]', '') ;
integer_part := TO_NUMBER(integer_part_str);
integer_part  := integer_part  + 1 ;
integer_part_str  := TO_CHAR(integer_part) ;
out_id  :=  string_part + integer_part_str   ;
return out_id;
END;

我在数据库中有一个名为 BRANDS 的 table,列 BRAND_ID 的最大值是 'Brand05'。预期输出为 'Brand06'.

然而当我运行: select get_id5('BRAND_ID' , 'BRANDS') from dual;

DECLARE
a VARCHAR(32) ;
BEGIN
a := get_id5('BRAND_ID' , 'BRANDS');
END;

我收到以下错误:

ORA-00923: FROM keyword not found where expected

FROM 和 table_name 之间需要空格,INTO 应该在 SQL 文本之外:

execute immediate 'select MAX('||in_col_name||') FROM ' || in_tbl_name INTO full_id;

您也可以使用 DBMS_ASSERT:

execute immediate 'select MAX('||DBMS_ASSERT.SIMPLE_SQL_NAME(in_col_name)||') FROM ' || DBMS_ASSERT.SIMPLE_SQL_NAME(in_tbl_name) INTO full_id;

然后你需要使用 || 作为字符串连接运算符(而不是 +)。

您的函数可以是:

create or replace function get_id5(
  in_col_name IN VARCHAR2,
  in_tbl_name IN VARCHAR2
) RETURN VARCHAR2
IS
  full_id VARCHAR2(32);
BEGIN
  execute immediate 'select MAX('||DBMS_ASSERT.SIMPLE_SQL_NAME(in_col_name)||') '
                  || 'FROM ' || DBMS_ASSERT.SIMPLE_SQL_NAME(in_tbl_name)
                  INTO full_id;
  return regexp_replace(full_id , '\d+', '')
         || TO_CHAR(regexp_replace(full_id , '\D+', '') + 1);
END;
/

示例数据:

CREATE TABLE brands (brand_id) AS
SELECT 'BRAND5' FROM DUAL;

然后:

select get_id5('BRAND_ID' , 'BRANDS') AS id from dual;

输出:

ID
BRAND6

db<>fiddle here


更好的解决方案

要生成数字,请使用 SEQUENCE 或 Oracle 12 中的 IDENTITY 列,如果您必须有字符串前缀,则使用虚拟列来生成它。

CREATE TABLE brands(
  ID NUMBER
     GENERATED ALWAYS AS IDENTITY
     PRIMARY KEY,
  brand_id VARCHAR2(10)
           GENERATED ALWAYS
             AS (CAST('BRAND' || TO_CHAR(id, 'FM000') AS VARCHAR2(10)))
);

BEGIN
  INSERT INTO brands (id) VALUES (DEFAULT);
  INSERT INTO brands (id) VALUES (DEFAULT);
  INSERT INTO brands (id) VALUES (DEFAULT);
END;
/

SELECT * FROM brands;

输出:

ID BRAND_ID
1 BRAND001
2 BRAND002
3 BRAND003

db<>fiddle here