在 Oracle 19c 中从 LONG 中提取字符

Extract characters from a LONG in Oracle 19c

提问人:Charles 提问时间:10/19/2023 更新时间:10/19/2023 访问量:70

问:

我有一个表t,其中的c列类型为LONG。我想提取最后 100 个字符。

难点在于:

  1. 字符串函数不适用于 LONG。
  2. 将 LONG 转换为 CLOB 是很困难的,即使to_lob和 cast 似乎也失败了
  3. 这些值可能超过 VARCHAR 的长度。

我尝试了最明显的解决方案:

select right(to_lob(c), 100) from t

失败

数据类型不一致:预期的 CHAR 变长

和 CTE

with foo as (
  select cast(to_lob(c) as clob) c
)
select substr(c, length(c)-99, 100) ending
from foo

这给出了相同的错误。

SQL 字符串 oracle oracle19c

评论

0赞 PM 77-1 10/19/2023
通读 oracle-developer.net/display.php?id=430(如果您尚未这样做)。

答:

0赞 Paul W 10/19/2023 #1

如果长整型值的大小< 32KB,则只需将它们分配给 PL/SQL 中的局部变量即可。如果它们小于 4KB,则特别容易,因为这样我们就可以返回一个可访问的 SQL。以下是它的外观:varchar2varchar2

CREATE TYPE foo_rowtype IS OBJECT (long_col1 varchar2(4000), col2 int, col3 varchar2(5)); -- all the columns needed from the table
CREATE TYPE foo_tabtype IS TABLE OF foo_rowtype;

CREATE OR REPLACE FUNCTION foo2string
  RETURN foo_tabtype PIPELINED
AS
  var_string varchar2(32767);
BEGIN
  FOR rec_row IN (SELECT *
                    FROM foo)
  LOOP
    var_string := rec_row.long_col1; -- long to varchar2 conversion here
    PIPE ROW(foo_rowtype(SUBSTR(var_string,1,4000),rec_row.col2,rec_row.col3));
  END LOOP;
END;
/

-- now query it normally, in this case getting the last 100 chars:
 SELECT SUBSTR(long_col1,LENGTH(long_col1)-100)),col2,col3
  FROM foo2string

-- older versions may require the TABLE operator:

SELECT SUBSTR(long_col1,LENGTH(long_col1)-100)),col2,col3
  FROM TABLE(foo2string)

如果值大于 4KB,则需要让函数本身获取字符串的末尾。如果它们超过 32KB,那么您将不得不使用一种更复杂的方法,包括通过迭代调用逐步读取 long 并附加到临时 CLOB 中。要复杂得多。这就是为什么我们从不使用 long 数据类型的原因。在某些视图中,唯一应该找到它的位置是在 Oracle 的数据字典中,并且可以使用上述技术使这些视图可通过代码进行管理。dbms_sqldbms_sql.column_value_long

0赞 p3consulting 10/19/2023 #2

尝试

select dbms_lob.substr(sys_dburigen(LIST_OF_COLUMNS_LEADING_TO_UNIQUE_ROW, c, 'text()').getclob(),4000,1) as c
from foo ; 

如果你的牌桌里有一个PK,那么LIST_OF_COLUMNS_LEADING_TO_UNIQUE_ROW是微不足道的。

例:

select index_name, column_position, dbms_lob.substr(sys_dburigen(index_owner, index_name, column_position, column_expression, 'text()').getclob(),4000,1) as ce
from all_ind_expressions ;