更新Firebird BLOB字段附加文本

时间:2019-03-07 15:22:11

标签: firebird firebird2.1

问题

当此值为 NULL 时,不能使用简单的concat( || )将文本附加到Blob字段。

文档库:https://firebirdsql.org/refdocs/langrefupd21-blob.html

测试环境

enter image description here

假设类型:

  • fieldTarget〜 BLOB
  • tablePk〜 VARCHAR(5)

赞:

UPDATE tablename
SET fieldTarget = fieldTarget || :string
WHERE tablePk = :pkTarget;

执行后,没有任何错误返回,但字段仍然

3 个答案:

答案 0 :(得分:0)

所有字符串操作(如||-串联)都受最大VarChar大小限制(32 KB,在UTF-8编码的文本中小于8200个字母)限制。

但是似乎有面向BLOB的函数。它还不需要使用NULL来转义COALESCE值。

  

LIST返回一个字符串,该字符串由组中的非NULL参数值组成,并用逗号或用户提供的定界符分隔

https://firebirdsql.org/refdocs/langrefupd21-aggrfunc-list.html

因此,使用derived tables

Select LIST(ALL X, '') From
 ( Select fieldTarget as x From tablename Where tablePk = :pkTarget
      UNION ALL
   Select Cast( :string AS VarChar(8191) ) From RDB$DATABASE ) 
As TMP

类型转换是将数据类型分配给仅参数表达式。

P.S。该文档还声称

  

列表值的顺序未定义。

P.P.S。准备运行的示例,在FB 2.1.7上进行了测试

Select LIST(ALL X, '') From
 ( Select Cast( :str_pre AS VarChar(8191) ) as X From RDB$DATABASE
      UNION ALL
   Select /* DATA column */ RDB$TRIGGER_SOURCE
          From /* DATA table */ RDB$TRIGGERS
          Where /* PK ID */ RDB$TRIGGER_NAME  = :pkTarget
      UNION ALL
   Select Cast( :str_post AS VarChar(8191) ) From RDB$DATABASE
)

传递诸如RDB$TRIGGER_1之类的名称将为您提供一个system trigger,该文本没有源文本,因此该字段中的值为NULL。易于检查,无需在这里进行COALESCE筛选:-D

答案 1 :(得分:0)

您遇到的主要问题是原始值为NULL。对NULL值进行加法,串联等操作将产生NULL。要深入了解NULL的详细信息,请考虑阅读Firebird Null Guide

解决方案是在列为null *时使用COALESCE提供默认值(例如,空字符串)。

UPDATE tablename
SET fieldTarget = COALESCE(fieldTarget, '') || :string
WHERE tablePk = :pkTarget;

*:您现在已经删除的答案中已经包含了此内容,但是对varchar的强制转换有点不必要了,

答案 2 :(得分:0)

您可以尝试在 COALESCE 中使用 CAST(“your blob null field”作为“MY BLOB DOMAIN OF SUBTYPE_1”的类型),它对我有用(在 firebird 2.1 中测试)

Firebird CAST

Firebird COALESCE

在我测试的情况下,我有一个带有下一个域信息的“空”blob字段(让我们称他为“NOTES”):

<块引用>

BLOB SUB_TYPE 0 段大小 80

执行 COALESCE(NOTES, '') 会返回下一个错误:

<块引用>

数据类型在表达式 COALESCE 中不可比较

诀窍是创建 BLOB SUB_TYPE 1 的(我们称他为“TEXT”)并在连接或获取它之前对该域进行 CAST:

SELECT COALESCE(CAST(NOTES AS TYPE OF TEXT), '') FROM MY_TABLE

在您的情况下,下一个案例必须正常工作:

UPDATE tablename
SET fieldTarget = COALESCE(CAST(:fieldTarget AS TYPE TEXT), '') || :string
WHERE tablePk = :pkTarget;

之前在数据库中创建域TEXT作为blob sub_type 1的帐户。

PD:真正的技巧是投射到将要更新的字段的域。