Informix 9.52C1 - 替换回车和换行

时间:2016-06-09 00:17:22

标签: replace escaping informix

我搜索谷歌并找不到任何真正帮助我的东西IBM网站显示Informix 11.5及以上的功能,比如他们已停止支持9.52C1或其他东西。因此我在这里的原因。

正如主题所述,我正在使用Informix 9.52C1。我使用SQL获取此信息:

SELECT owner FROM systables WHERE TABNAME= ' VERSION';

我不确定是否支持替换功能,因为当我执行语句时:

SELECT col1, REPLACE('r','p','poster') as col2 FROM table;

列col2只包含字母'r'但是虽然我使用了REPLACE()函数但没有抛出错误。

我知道可以使用“\ r \ n”转义格式找到转义字符(CRLF),因为此SQL可以正常工作:

SELECT *  FROM table WHERE col1 LIKE '%\r\n%';

注意:我使用上面的SQL来检索版本号,因为我只能通过客户端数据库应用程序访问。但是,如果您可以访问运行informix数据库服务器的实际主机,我确信有一些命令争论来解析版本,可能是defualt linux --version或-v争论与db服务器应用程序。

这确实只返回了包含CRLF的记录。

我的主要工作是在CR和LF前面放一个反斜杠,因为我正在将数据从Informix 9.52C1迁移到PostgreSQL数据库。我打算使用COPY函数将数据加载到PostgreSQL数据库,并且COPY函数以这种方式工作,因为我已经完成了测试记录。我的困境是以正确的格式从Informix中提取数据。任何人都可以帮助解决这个问题吗?

我试过了:

SELECT REPLACE('\\\r\\\n','\r\n',col1) as description FROM table;

然而这不起作用我相信由于替换功能,我提到我不确定此Informix版本中是否有替换功能。

提前致谢,

jerg

P.S。 ASCII(),CHAR()和CHR()函数都不起作用。一些网站建议这些功能。但据我所知,功能CHR()& ASCII()在verison 11.5+中实现。这个post建议了这些功能。

2 个答案:

答案 0 :(得分:1)

要在数据库之间迁移数据,您可以使用JDBC驱动程序(我使用Jython,但Java或其他可以使用JDBC驱动程序的语言都可以),然后SELECT ...来自源数据库(Informix)和INSERT ...只需将数据读入目标(PostgreSQL)。使用BatchInsert或PreparedStatement它真的很快。在我的代码中,它看起来像:

insert_str = 'INSERT INTO ' + table_name + ' (' + column_names + ') VALUES (' + question_marks + ')'
insert_stmt = db_to.prepareStatement(insert_str)
...
pstm2 = db_from.createStatement()
rs_in = pstm2.executeQuery('SELECT %s FROM %s %s' % (column_names, table_name, order_str))
...
while (rs_in.next()):
    for i in range(1, col_count + 1):
        insert_stmt.setObject(i, rs_in.getObject(i))

当然你必须处理错误,自动提交,获取大小等等,但我认为值得你努力。

您对COPY ...的想法也很好。你在文本文件中保存Informix的输出吗?如果它在文本文件中,您可以在将文本文件导入PostgreSQL之前简单地更正它。

答案 1 :(得分:1)

我不认识9.52C1版。 Informix版本可能是9.52.UC1 - 第一个字母可以选择UFWHT。但话说回来,主要版本号是9.00..9.03,9.10..9.16,9.20,9.21,9.30,9.40,10.00,11.10,11.50,11.70,12.10 - 一个不包括9和5的序列单个版本。那么,在很多方面,它并不重要;任何版本9.x在十年的大部分时间里都已失去支持,如果不是更长的话,并且不应该继续使用。

假设升级到现有版本的Informix不在卡中,您将无法实现自己的功能。要完成这项工作,您最好在C中实现它们,并将它们作为UDR包(用户定义的例程)安装在共享库中。这会给你最好的表现。假设这不可行(我手边没有一组这样的函数,但编写它们并不困难),那么你必须回到SPL(存储过程语言)例程。由于SPL w.r.t子字符串操作的限制,这些快 - 具体地说,带有[]表示法的内置子字符串操作不接受变量作为下标。对于礼貌而言,这真的很痛苦。

这是char_at的一个版本,它在最多255个字符的字符串中的给定位置获取单个字符:

-- @(#)$Id: char_at.spl,v 1.1 1999/05/17 23:59:59 jleffler Exp $
--
-- CHAR_AT stored procedure, to return character at given position in string
--
-- Author: J Leffler
-- Date: 1999-05-17

CREATE PROCEDURE char_at(str VARCHAR(255), pos SMALLINT) RETURNING CHAR(1);

    DEFINE c CHAR(1);

    IF pos > LENGTH(str) OR pos <= 0 THEN
        LET c = NULL;
    ELIF pos <= 16 THEN
        IF   pos =  1 THEN LET c = str[ 1];
        ELIF pos =  2 THEN LET c = str[ 2];
        ELIF pos =  3 THEN LET c = str[ 3];
        ELIF pos =  4 THEN LET c = str[ 4];
        ELIF pos =  5 THEN LET c = str[ 5];
        ELIF pos =  6 THEN LET c = str[ 6];
        ELIF pos =  7 THEN LET c = str[ 7];
        ELIF pos =  8 THEN LET c = str[ 8];
        ELIF pos =  9 THEN LET c = str[ 9];
        ELIF pos = 10 THEN LET c = str[10];
        ELIF pos = 11 THEN LET c = str[11];
        ELIF pos = 12 THEN LET c = str[12];
        ELIF pos = 13 THEN LET c = str[13];
        ELIF pos = 14 THEN LET c = str[14];
        ELIF pos = 15 THEN LET c = str[15];
        ELIF pos = 16 THEN LET c = str[16];
        END IF;
    ELIF pos <=  32 THEN LET c = char_at(str[ 17, 32], pos -  1 * 16);
    ELIF pos <=  48 THEN LET c = char_at(str[ 33, 48], pos -  2 * 16);
    ELIF pos <=  64 THEN LET c = char_at(str[ 49, 64], pos -  3 * 16);
    ELIF pos <=  80 THEN LET c = char_at(str[ 65, 80], pos -  4 * 16);
    ELIF pos <=  96 THEN LET c = char_at(str[ 81, 96], pos -  5 * 16);
    ELIF pos <= 112 THEN LET c = char_at(str[ 97,112], pos -  6 * 16);
    ELIF pos <= 128 THEN LET c = char_at(str[113,128], pos -  7 * 16);
    ELIF pos <= 144 THEN LET c = char_at(str[129,144], pos -  8 * 16);
    ELIF pos <= 160 THEN LET c = char_at(str[145,160], pos -  9 * 16);
    ELIF pos <= 176 THEN LET c = char_at(str[161,176], pos - 10 * 16);
    ELIF pos <= 192 THEN LET c = char_at(str[177,192], pos - 11 * 16);
    ELIF pos <= 208 THEN LET c = char_at(str[193,208], pos - 12 * 16);
    ELIF pos <= 224 THEN LET c = char_at(str[209,224], pos - 13 * 16);
    ELIF pos <= 240 THEN LET c = char_at(str[225,240], pos - 14 * 16);
    ELIF pos <= 255 THEN LET c = char_at(str[241,255], pos - 15 * 16);  -- Note asymmetry in upper bound!
    ELSE                 LET c = NULL;  -- Not reached!
    END IF;

    RETURN c;

END PROCEDURE;

处理一般子串等同样是痛苦的。我从来没有努力构建SUBSTR的半性能SPL实现。升级到内置支持的Informix版本要好得多。

CHR()和ASCII()

CHR()ASCII()函数可以使用以下函数进行模拟:

-- @(#)$Id: chr.sql,v 1.2 2008/09/19 18:48:37 jleffler Exp $
--
-- @(#)Procedure CHR() - return character corresponding to integer

CREATE PROCEDURE chr(i INTEGER) RETURNING CHAR(1) AS result;
    DEFINE c CHAR;
    IF i < 0 OR i > 255 THEN
        RAISE EXCEPTION -746, 0, 'CHR(): integer value out of range 0..255';
    END IF;
    IF i = 0 OR i IS NULL THEN
        LET c = NULL;
    ELSE
        SELECT chr INTO c FROM ascii WHERE val = i;
    END IF;
    RETURN c;
END PROCEDURE;

-- @(#)$Id: ascii.sql,v 1.2 2008/09/19 18:40:19 jleffler Exp $
--
-- Procedure ASCII - returning integer corresponding to character.
-- Misnomer: it works on any single-byte character.

CREATE PROCEDURE jl_ascii(C CHAR) RETURNING INT AS result;
    DEFINE i INTEGER;
    IF c IS NULL THEN
        LET i = 0;
    ELSE
        SELECT val INTO i FROM ascii WHERE chr = c;
    END IF;
    RETURN i;
END PROCEDURE;

需要一张表:

-- @(#)$Id: asciitbl.sql,v 1.2 2005/03/30 17:51:12 jleffler Exp $
--
-- @(#)Create ASCII Table (for ASCII and CHR functions).

CREATE TABLE ascii
(
    val     INTEGER NOT NULL UNIQUE CONSTRAINT u1_ascii,
    chr     CHAR(1) NOT NULL UNIQUE CONSTRAINT u2_ascii
);
REVOKE ALL ON ascii FROM PUBLIC;
GRANT SELECT ON ascii TO PUBLIC;

以及要输入的数据 - 255行,例如:

…
32| 
33|!
34|"
35|#
36|$
37|%
38|&
39|'
40|(
…
64|@
65|A
66|B
67|C
68|D
69|E
…

您应该可以在名为 ascii IIUG处找到此代码的副本。