我正在编写一个模拟 Informix UNLOAD 的存储过程,这样我就可以将输出放入一个竖线分隔的文本文件中,以便传输到另一个系统。我的过程按预期工作,但是当我将输出重定向到我的 shell 脚本中的文本文件时,这些行在 66 个字符后中断。我需要每条记录都在自己的行上,记录中没有换行符。
它为每条记录返回的文本字符串最长可达 350 个字符。是否存在导致这种情况发生的 Informix 设置?我的 shell 脚本中有什么?
整个过程如下。我还添加了代码,展示了我如何从 shell 脚本调用此 SP。
我们使用的是 Solaris 10 和 Informix IDS 11.70。
我看到了 answer关于之前在存储过程中执行 UNLOAD 的 SO 问题。目前,首选是避免使用临时表和外部表。 (但如果我们不能让这种方法起作用,我们可能会回到那个解决方案。)
# Real script receives these as args or calculates using today's date
begin_date="2019-04-26 00:00:00"
end_date="2019-04-26 23:59:59"
dbname="mydatabase"
STORED_PROCEDURE="sp_unload_mytable"
OUTFILE="return.dat"
rm -f $OUTFILE
echo "execute procedure ${STORED_PROCEDURE}('${begin_date}','${end_date}') " | dbaccess $dbname \
| sed 's,(expression),,' | sed 's/,$//' | sed -e '/^$/d' | sed 's/^[ ]*//' > $OUTFILE
create procedure sp_unload_mytable(start_date datetime year to second, end_date datetime year to second)
returning lvarchar(500);
DEFINE p_rep_serial integer;
DEFINE p_post_flag integer;
DEFINE p_recording_date varchar(8);
DEFINE p_lastname varchar(35);
DEFINE p_firstname varchar(20);
DEFINE p_middlename varchar(20);
DEFINE p_generation varchar(4);
DEFINE p_role varchar(8);
DEFINE p_corporperson varchar(1);
DEFINE p_party_type varchar(1);
DEFINE p_b varchar(5);
DEFINE p_p varchar(4);
DEFINE p_item_number varchar(4);
DEFINE p_i_code varchar(3);
DEFINE p_i_desc varchar(10);
DEFINE p_par_id varchar(12);
DEFINE p_ref_b varchar(5);
DEFINE p_ref_p varchar(4);
DEFINE p_remark_1 varchar(20);
DEFINE p_remark_2 varchar(20);
DEFINE p_i_id varchar(10);
DEFINE p_ret_code varchar(12);
DEFINE p_nbr_of_attempts varchar(12);
DEFINE p_insert_timestamp datetime year to second;
DEFINE p_edit_flag varchar(12);
DEFINE p_document_id varchar(12);
DEFINE p_version varchar(6);
DEFINE p_attempts varchar(6);
DEFINE p_return lvarchar(500);
FOREACH SELECT rep_serial, post_flag, nvl(recording_date, ""),
nvl(lastname, ""), nvl(firstname, ""), nvl(middlename, ""),
nvl(trim(generation), ""), nvl(trim(role), ""),
nvl(trim(corporperson), ""), nvl(trim(party_type), ""),
nvl(trim(b), ""), nvl(trim(p), ""), nvl(trim(item_number), ""),
nvl(trim(i_code), ""), nvl(trim(i_desc), ""),
nvl(par_id, ""), nvl(trim(ref_b), ""),
nvl(trim(ref_p), ""), nvl(remark_1, ""), nvl(remark_2, ""),
nvl(i_id, ""), nvl(ret_code, ""), nvl(nbr_of_attempts, ""),
nvl(insert_timestamp, ""), nvl(edit_flag, ""), nvl(document_id, ""),
nvl(version, ""), nvl(attempts, "")
INTO p_rep_serial, p_post_flag, p_recording_date, p_lastname, p_firstname,
p_middlename, p_generation, p_role, p_corporperson, p_party_type,
p_b, p_p, p_item_number, p_i_code, p_i_desc,
p_par_id, p_ref_b, p_ref_p, p_remark_1,
p_remark_2, p_i_id, p_ret_code, p_nbr_of_attempts,
p_insert_timestamp, p_edit_flag, p_document_id, p_version, p_attempts
from mytable
where insert_timestamp between start_date and end_date
LET p_return = p_rep_serial || "|" || p_post_flag || "|" || p_recording_date || "|" || p_lastname || "|" || p_firstname || "|" || p_middlename || "|" || p_generation || "|" || p_role || "|" || p_corporperson || "|" || p_party_type || "|" || p_b || "|" || p_p || "|" || p_item_number || "|" || p_i_code || "|" || p_i_desc || "|" || p_par_id || "|" || p_ref_b || "|" || p_ref_p || "|" || p_remark_1 || "|" || p_remark_2 || "|" || p_i_id || "|" || p_ret_code || "|" || p_nbr_of_attempts || "|" || p_insert_timestamp || "|" || p_edit_flag || "|" || p_document_id || "|" || p_version || "|" || p_attempts;
RETURN p_return WITH RESUME;
END FOREACH;
end procedure;
最佳答案
导致问题的是 DB-Access。
如果您使用的是足够新的 Informix 版本(12.10.xC12 或 14.10.xC1 或更高版本,在每个版本系列中),您可以使用环境变量 DBACCESS_COLUMNS
来设置有效“屏幕”(输出)的宽度。但是,如果数据本身包含换行符,那么这些将反射(reflect)在输出中。除了将输出强制转换为 JSON(这不是特别容易,但如果您好奇的话可以查找 genBSON
),我不知道有什么方法可以删除换行符或用 \替换它们n
或类似的,除了通过后处理 DB-Access 输出。
由于您的 Informix (11.70) 版本太旧,无法支持 DBACCESS_COLUMNS
,我不确定是否有真正好的替代方案。
必要时,您可以使用我的 SQLCMD程序(与 Microsoft 的同名 johnny-come-lately interloper 无关)。要在那里获得它,您必须加入 IIUG(国际 Informix 用户组),它是免费的并且不涉及太多电子邮件(除非您订阅任何邮件列表,否则每月一两封)。 SQLCMD 优于 DB-Access 的优点是它会自动执行“尽可能宽”的输出,但它没有“不直接包含换行符”的输出模式,除非通过它的 JSON 样式输出(我看到我需要在 v91.03 中修复错误,它比 IIUG 网站上的更新——目前它不是一个足够有用的选项)。我会考虑添加一个“C 风格转义输出”选项(或者它可能只是 JSON 风格,因为我无论如何都需要更好地处理 JSON — 待定)。 SQLCMD 应该可以与您可以使用的几乎任何版本的 Informix (ESQL/C) 一起编译。
关于sql - 如何防止从 Informix 存储过程返回的长文本值中出现换行符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55874741/