Oracle SQL - substr 参数硬编码

问题描述 投票:0回答:2

我有一个包含“foo”列的表,其数据类型是varchar2(100)。

在此表中,我在“foo”列中有一行包含一些信息。假设它是字符串“bar”。

然后我有一个过程可以复制行、更改数据并将其插入表中。其中一项更改是在“foo”列的开头添加字符串“xyz,”并将其余部分连接起来。因此,当我运行此过程时,它会在“foo”列中生成包含字符串“xyz,bar”的行。 下次运行此过程时,我会在“foo”列中得到字符串“abc,xyz,bar”等。

为了不遇到错误,我这样编写代码:

Insert into table (
foo
) values (
substr(variable_with_additional_string || variable_with_string_from_foo_column, 1, 100)
);

如果绳子太长,我总是剪掉最后一部分。

但是如果有人更改表并将列“foo”的数据类型更改为 varchar2(80) 该怎么办?我的程序将不再有效。

所以我的问题是:如何不在 substr() 函数中硬编码数字 100?

我唯一的想法是

SELECT DATA_TYPE
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME = 'table'
  AND COLUMN_NAME = 'foo';

并使用正则表达式或其他函数查找数字,但我认为这不是最佳方法,所以解决这个问题。

sql oracle plsql
2个回答
0
投票

您可以使用简单的选择查询来获取列的数据长度,例如:

SELECT DATA_LENGTH
INTO v_max_length
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME = 'table'
AND COLUMN_NAME = 'foo';

然后在插入的 substr 函数中使用该值:

Insert into table 
(
   foo
) 
values 
(
    substr(variable_with_additional_string || variable_with_string_from_foo_column, 1, v_max_length)
);

0
投票

如果你想将字符串的长度限制为列的长度,我认为你不能在 SQL 中做到这一点 - 但你可以在 PL/SQL 中,编写一个将修改该表的过程。这是一个例子。

样本表:

SQL> create table test (id number, col varchar2(10));

Table created.

程序检查

user_tab_columns
并使用
merge
upsert
col
列,其中包含
par_col
参数的子字符串(连接到前一列内容),直至最大列长度。

SQL> create or replace procedure p_test
  2    (par_id  in test.id%type,
  3     par_col in test.col%type)
  4  is
  5    l_data_length user_tab_columns.data_length%type;
  6  begin
  7    select data_length
  8      into l_data_length
  9      from user_tab_columns
 10      where table_name = 'TEST'
 11        and column_name = 'COL';
 12
 13    merge into test a
 14      using (select par_id  as id,
 15                    par_col as col
 16             from dual
 17            ) x
 18      on (a.id = x.id)
 19      when matched then update set
 20        a.col = substr(par_col || ','|| a.col, 1, l_data_length)
 21      when not matched then insert (id, col)
 22        values (par_id, substr(par_col, 1, l_data_length));
 23  end;
 24  /

Procedure created.

测试:

SQL> exec p_test (1, 'abc');

PL/SQL procedure successfully completed.

SQL> select * From test;

        ID COL
---------- ----------
         1 abc

SQL> exec p_test(1, '12345678');

PL/SQL procedure successfully completed.

SQL> select * From test;

        ID COL
---------- ----------
         1 12345678,a

您担心缩短柱的长度;这可能是可能的,也可能是不可能的(以简单的方式):

SQL> alter table test modify col varchar2(5);
alter table test modify col varchar2(5)
                        *
ERROR at line 1:
ORA-01441: cannot decrease column length because some value is too big

一个选择是首先缩短现有内容:

SQL> update test set col = substr(col, 1, 5);

1 row updated.

SQL> alter table test modify col varchar2(5);

Table altered.

SQL> select * From test;

        ID COL
---------- -----
         1 12345

我们再测试一下:

SQL> exec p_test (1, 'xyz');

PL/SQL procedure successfully completed.

SQL> select * From test;

        ID COL
---------- -----
         1 xyz,1

SQL>

另一方面,你为什么允许任何人改变表格?

© www.soinside.com 2019 - 2024. All rights reserved.