是否可以将 varchar(32) 的字段转换为 Firebird 数据库中的 BLOB
Is it possible to convert a field of varchar(32) to BLOB in Firebird database
我想保留已保存到 Table 字段 varchar(32) 中的数据,并将其转换为 Firebird 数据库中的 BLOB。
我正在使用一个软件:IBExpert ....
如果可以的话,怎么做?
假设您有 table TEST,其中一列 NAME:
create table test (name varchar(32));
insert into test values('test1');
insert into test values('test2');
insert into test values('test3');
commit;
select * from test;
可以通过以下脚本将列从 varchar 更改为 BLOB:
alter table test add name_blob blob;
update test set name_blob = name;
commit;
alter table test drop name;
alter table test alter column name_blob to name;
commit;
select * from test;
特别是在 IBExpert
中,通过直接修改系统 tables 可以很容易地使用 Firebird 2.1
和 Firebird 2.5
(此 "obsolete" 方法在Firebird 3
但没有引入任何东西来替代它。
这在两个方向上都有效,VARCHAR
到 BLOB
和 BLOB
到 VARCHAR
。
您必须有一个 DOMAIN
- 即命名数据类型,在 SQL 中,并且该域应该是 BLOB
类型 - 然后是 IBExpert
如果您在数据库选项中设置 Firebird 2.x,它本身会发出 Firebird 2.x
执行的命令。
如果您没有 IB Expert
那么您必须发出以下命令:
CREATE DOMAIN T_TEXT_BLOB AS -- prerequisite
BLOB SUB_TYPE 1;
update RDB$RELATION_FIELDS -- the very action
set RDB$FIELD_SOURCE = 'T_TEXT_BLOB'
/* the name of the blob domain to be set as the field's new data type */
where RDB$FIELD_SOURCE = '.....' /* name of the column */
and RDB$RELATION_NAME = '....' /* name of the table */
另请参阅:
- https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-ddl-domn.html
- https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref-appx04-relfields.html
当您创建列或更改其数据类型而没有明确命名类型(如 varchar(10)
)时,Firebird 会在后台创建自动管理的每列一个用户域,名称如 RDB345
,所以虽然你也可以这样做,但也许明确命名 domain
会更实用也更安全。
然而,此方法在 Firebird 3 上失败,您必须复制整个 table,如上面的 Maxim 所示。
FB 开发人员对某些 "bugs" 和 "it never worked properly" 发出警告,但拒绝提供详细信息。
更新 我终于重现了跟踪器中提到的错误。
至少在 Firebird 2.1 中引用计数被破坏了 w.r.t。 BLOB 负载。
所以诀窍似乎是立即将隐式 blob 重写为显式,欺骗 Firebird 认为我们为所有 BLOB 值提供了 新内容。
假设上面 Maxim 的回答中的名字...
触发和演示错误 获取 "vanilla" VarChar
数据库,应用上述转换,并发出以下命令:
update test set name = name
-- 试图强制数据转换,但却强制 Firebird 引用计数错误
select cast( name as VarChar(200) ) from test
- 或者实际上任何试图实际读取字段内容的命令 - 任何此类尝试都会因臭名昭著的 invalid BLOB ID
Firebird 错误而被击落。
要解决错误,我们必须防止 Firebird 发生(损坏的)引用计数。所以,我们必须做一个假更新,调用表达式求值器,这样 Firebird 优化器就会失去对值来源的跟踪,并且无法意识到数据并没有真正改变。
update test set name = '' || name || ''
-- 真正强制数据覆盖和转换,绕过BLOB引用计数。
select cast( name as VarChar(200) ) from test
- 现在就像一个魅力(尽管 200 太短了,你会遇到 "overflow" 错误
update
命令可以是任何其他触发表达式求值器,例如 update test set name = cast( name as VarChar( NNN ) )
- 但您需要为特定 table 的特定列设计足够大的 NNN。因此,字符串与空字符串的连接是通用的并且可以工作,至少在 Firebird 2.1 上是这样。
以上代表Firebird 2.1.7 Win32。我没有设法用 Firebird 2.5.8 Win64 触发 "invalid BLOB id" - 它 "just worked"。
至少使用单连接模式更新脚本,无论如何这是进行数据库升级的预期方式。
也许如果我在进行模式升级的同时会有用户积极工作——FB 2.5 也会被破坏,不知道。
是不顾FB开发人员的提示,使用这种快捷方式有风险,还是使用"official" Maxim的回答,可能卸载然后重新创建恰好有"dependencies"的一半数据库要删除的字段,保持到 reader.
我想保留已保存到 Table 字段 varchar(32) 中的数据,并将其转换为 Firebird 数据库中的 BLOB。 我正在使用一个软件:IBExpert .... 如果可以的话,怎么做?
假设您有 table TEST,其中一列 NAME:
create table test (name varchar(32));
insert into test values('test1');
insert into test values('test2');
insert into test values('test3');
commit;
select * from test;
可以通过以下脚本将列从 varchar 更改为 BLOB:
alter table test add name_blob blob;
update test set name_blob = name;
commit;
alter table test drop name;
alter table test alter column name_blob to name;
commit;
select * from test;
特别是在 IBExpert
中,通过直接修改系统 tables 可以很容易地使用 Firebird 2.1
和 Firebird 2.5
(此 "obsolete" 方法在Firebird 3
但没有引入任何东西来替代它。
这在两个方向上都有效,VARCHAR
到 BLOB
和 BLOB
到 VARCHAR
。
您必须有一个 DOMAIN
- 即命名数据类型,在 SQL 中,并且该域应该是 BLOB
类型 - 然后是 IBExpert
如果您在数据库选项中设置 Firebird 2.x,它本身会发出 Firebird 2.x
执行的命令。
如果您没有 IB Expert
那么您必须发出以下命令:
CREATE DOMAIN T_TEXT_BLOB AS -- prerequisite
BLOB SUB_TYPE 1;
update RDB$RELATION_FIELDS -- the very action
set RDB$FIELD_SOURCE = 'T_TEXT_BLOB'
/* the name of the blob domain to be set as the field's new data type */
where RDB$FIELD_SOURCE = '.....' /* name of the column */
and RDB$RELATION_NAME = '....' /* name of the table */
另请参阅:
- https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-ddl-domn.html
- https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref-appx04-relfields.html
当您创建列或更改其数据类型而没有明确命名类型(如 varchar(10)
)时,Firebird 会在后台创建自动管理的每列一个用户域,名称如 RDB345
,所以虽然你也可以这样做,但也许明确命名 domain
会更实用也更安全。
然而,此方法在 Firebird 3 上失败,您必须复制整个 table,如上面的 Maxim 所示。
FB 开发人员对某些 "bugs" 和 "it never worked properly" 发出警告,但拒绝提供详细信息。
更新 我终于重现了跟踪器中提到的错误。
至少在 Firebird 2.1 中引用计数被破坏了 w.r.t。 BLOB 负载。 所以诀窍似乎是立即将隐式 blob 重写为显式,欺骗 Firebird 认为我们为所有 BLOB 值提供了 新内容。
假设上面 Maxim 的回答中的名字...
触发和演示错误 获取 "vanilla" VarChar
数据库,应用上述转换,并发出以下命令:
update test set name = name
-- 试图强制数据转换,但却强制 Firebird 引用计数错误select cast( name as VarChar(200) ) from test
- 或者实际上任何试图实际读取字段内容的命令 - 任何此类尝试都会因臭名昭著的invalid BLOB ID
Firebird 错误而被击落。
要解决错误,我们必须防止 Firebird 发生(损坏的)引用计数。所以,我们必须做一个假更新,调用表达式求值器,这样 Firebird 优化器就会失去对值来源的跟踪,并且无法意识到数据并没有真正改变。
update test set name = '' || name || ''
-- 真正强制数据覆盖和转换,绕过BLOB引用计数。select cast( name as VarChar(200) ) from test
- 现在就像一个魅力(尽管 200 太短了,你会遇到 "overflow" 错误
update
命令可以是任何其他触发表达式求值器,例如 update test set name = cast( name as VarChar( NNN ) )
- 但您需要为特定 table 的特定列设计足够大的 NNN。因此,字符串与空字符串的连接是通用的并且可以工作,至少在 Firebird 2.1 上是这样。
以上代表Firebird 2.1.7 Win32。我没有设法用 Firebird 2.5.8 Win64 触发 "invalid BLOB id" - 它 "just worked"。 至少使用单连接模式更新脚本,无论如何这是进行数据库升级的预期方式。 也许如果我在进行模式升级的同时会有用户积极工作——FB 2.5 也会被破坏,不知道。
是不顾FB开发人员的提示,使用这种快捷方式有风险,还是使用"official" Maxim的回答,可能卸载然后重新创建恰好有"dependencies"的一半数据库要删除的字段,保持到 reader.