0

我有一个包含一组名称的列。我没有设计数据库,使其在一列中包含多个值,但现在我必须提取该信息。

问题是,在一个字段中,我有多个值,如本例所示:

“杰克汤姆拉里斯坦肯尼”

所以前三个应该是一组,最右边的其他是另一组。(基本上,在列中将它们分开的唯一因素是它们之间的特定数量的空白,比如说 50 个字符。)

如何将它们拆分为纯 SQL,以便我可以得到这样的两列:

专栏1“杰克汤姆拉里”
专栏2“斯坦肯尼”

4

1 回答 1

1

一个相当简单的答案是使用 left()、right() 和 locate() 的组合。像这样的东西(注意,为了便于阅读,我用“XXX”替换了 50 个空格):

declare global temporary table session.x(a varchar(100))
on commit preserve rows with norecovery;

insert into session.x values('Jack Tom LarryXXXStan Kenny');

select left(a,locate(a,'XXX')-1),right(a,length(a)+1-(locate(a,'XXX')+length('XXX'))) from session.x;

如果您需要一种更通用的方法从具有给定分隔符的字符串中提取第 n 个字段,有点像 PostgreSQL 中的 split_part() 函数,在 Ingres 中,您的选项将是:

使用对象管理扩展 (OME) 编写用户定义的函数。这并不完全简单,但在 Actian 社区网站的 wiki 页面中有一个很好的示例可以帮助您入门: http: //community.actian.com/wiki/OME :_User_Defined_Functions

创建行生成过程。使用起来比 OME 函数更笨重,但更容易实现。这是我对这样一个程序的尝试,虽然没有经过很好的测试,但它应该作为一个例子。您可能需要调整输入和输出字符串的宽度:

create procedure split
(
  inval = varchar(200) not null,
  sep = varchar(50) not null,
  n = integer not null
)
result row r(x varchar(200)) =

declare tno = integer not null;
        srch = integer not null;
        ptr = integer not null;
        resval = varchar(50);
begin
  tno = 1;
  srch = 1;
  ptr = 1;
  while (:srch <= length(:inval))
  do
    while (substr(:inval, :srch, length(:sep)) != :sep
      and :srch <= length(:inval))
    do
      srch = :srch + 1;
    endwhile;
    if (:tno = :n)
    then
      resval=substr(:inval, :ptr, :srch - :ptr);
      return row(:resval);
      return;
    endif;
    srch = :srch + length(:sep);
    ptr = :srch;
    tno = :tno + 1;
  endwhile;
  return row('');
end;

select s.x from session.x t, split(t.a,'XXX',2) s;
于 2016-09-21T08:19:02.333 回答