Informix 中的子字符串

Posted

技术标签:

【中文标题】Informix 中的子字符串【英文标题】:Substring in Informix 【发布时间】:2013-12-26 22:23:12 【问题描述】:

我需要根据 Informix 中的逗号将字段(名称)拆分为两个(名字和姓氏)。

示例:“Mark, Wheeler J”必须拆分为 Mark 和 Wheeler。我曾尝试使用 SQL 语法,但它在 Informix 中给我一个语法错误。请帮帮我。

SELECT
  SUBSTRING(name, 1, CHARINDEX(',', name ) - 1) AS FirstName,
  SUBSTRING(name, CHARINDEX(',', name) + 1, 8000) AS LastName
FROM
 employee

【问题讨论】:

您使用的是哪个版本:select dbinfo('version','full') from sysmaster:sysdualcharindex 函数仅在版本 11.70 中可用。 (在 11.70 版本中,您也可以使用 substring_index)。如果您使用的是旧版本,则需要创建一个过程来执行您的 cut 我使用的是低版本。你能告诉我有什么其他方法可以代替使用 charindex 吗?你能给我提供语法吗? 您使用的是哪个低版本?您可能不应该仍在使用它;版本 12.10 和 11.70 是主要支持的版本,而 11.50 即将获得支持。除非您与 IBM 做出特殊安排,否则不支持其他版本。您可以在 SPL 中编写一个 CHARINDEX 函数,但它不会很快。 这是我的版本#...IBM Informix Dynamic Server 版本 11.70.FC1GE.. 我也尝试过 substr()。它给了我一个错误,说“无法解决例程(charindex)。”我尝试了 substring_index() ,这对于这种情况来说是完美的,但它也给了我一个错误,说“无法解决例程(substring_index)”。是版本问题吗??有办法更新吗?? 好吧,我的错……这个例程是在 11.70xC3 添加的。这意味着第三个 FIX(缺陷更正,但 IBM 总是包含新特性)。当前版本/持续修复是 11.70xC7。您可以查看此news features here 【参考方案1】:

首先,如果您需要拆分这些值并且需要经常这样做,那么更改您的数据库架构会更容易:

    将列name 重命名为last_name 添加列first_name

它有一些优点。您可能想按姓氏搜索员工,只要有这样的列就很容易了。如果姓氏是name 列的一部分,那么您必须使用LIKE 进行搜索,这会更慢且更糟。

现在您将不得不更改一些数据。如果您在last_name 中有逗号,那么在该列中有名字和姓氏,您必须将其拆分。

如果你有 charindex() 函数,你可以这样做:

UPDATE employees SET last_name=substring(last_name FROM charindex(',', last_name)+1), first_name=substring(last_name FROM 1 FOR charindex(',', last_name)-1) WHERE charindex(',', last_name) > 0;

(您也可以使用TRIM() 删除将被复制的逗号前后的空格)

从 cmets 我看到您的 Informix 版本没有CHARINDEX() 功能,因此您必须升级数据库引擎或使用干净 SQL 以外的技术。

如果您可以使用 Java 或 Python 之类的编程语言(在此示例中,我使用 Jython:它是在 Java 环境中工作并且可以使用 JDBC 驱动程序的 Python),您可以:

db = DriverManager.getConnection(db_url, usr, passwd)
# prepare UPDATE:
pu = db.prepareStatement("UPDATE employee SET last_name=?, first_name=? WHERE id=?")

# search for names that must be changed:
pstm = prepareStatement("SELECT id, last_name FROM employee WHERE last_name LIKE '%,%')

# for each record found remember its `id`, split `first_name` and update it:

rs = pstm.executeQuery()
while (rs.next()):
    id = rs.getInt(1)
    name = rs.getString(2)
    first_name, last_name = name.split(',')
    pu.setString(1, last_name.strip())
    pu.setString(2, first_name.strip())
    pu.setInt(3, id)
    rc = pu.executeUpdate()

【讨论】:

【参考方案2】:

我遇到了类似的问题,所以我为informix 11.50 开发了一个下面的函数“char_cut”(没有在不同的版本上尝试过)请注意,这不是最有效的方法,但它工作正常。

用法:

SELECT
 char_cut(name, ',', 1) AS FirstName,
 char_cut(name, ',', 2) AS LastName
FROM
employee

程序:

create procedure char_cut( str_in varchar(255), separator_in char(1), field_in int  )
returning varchar(255) ;

define res varchar(255);
define str_len int;
define pos_curr int;
define substr_start int;
define substr_length int;
define pos_char char(1);

IF field_in <= 0 THEN return ''; END IF;

LET res = '';
LET substr_start = 0;
LET substr_length = 0;
LET str_len = length(str_in);

FOR pos_curr = 1 TO str_len

   LET pos_char = substr(str_in,pos_curr,1);
   IF pos_char = separator_in THEN
      LET field_in = field_in - 1;
   END IF;

   IF field_in = 1 and substr_start = 0 THEN
      LET substr_start = pos_curr + DECODE(pos_char,separator_in,1,0);
   END IF;

   IF field_in <= 0 THEN
      LET substr_length = pos_curr;
      EXIT FOR; --KONIEC 
   END IF;

END FOR;

IF substr_length = 0 THEN
   LET substr_length = str_len+1;
END IF;

IF substr_start = 0 THEN
   LET substr_start = str_len+1;
END IF;

IF substr_length < substr_start THEN
   LET substr_length = 0;
ELSE
   LET substr_length = substr_length - substr_start;
END IF;

RETURN NVL(substring ( str_in from substr_start for substr_length ),'');

end procedure;

【讨论】:

以上是关于Informix 中的子字符串的主要内容,如果未能解决你的问题,请参考以下文章

PB中取字符串子串的函数是啥

字符串子串去重之后的个数

[在python中使用正则表达式搜索字符串子字符串

sql server 里类似replace的字符串子串删除

2022华为机试真题 C++ 实现 字符串子序列II

华为OD机试真题Java实现判断字符串子序列真题+解题思路+代码(2022&2023)