将字符串与Firebird SQL中的尾随空格进行比较?

问题描述:

我有一个带有字符串[16]键字段的表的现有数据库。 有些行的键以空格结束:“16”。 我需要允许用户从“16”变成例如“16”,但也做一个独特的密钥检查(即表中没有key =“16”的记录)。 我运行以下查询:将字符串与Firebird SQL中的尾随空格进行比较?

select * from plu__ where store=100 and plu_num = '16' 

它返回的行与键= “16”! 如何检查唯一密钥,以便不包含尾随空格的密钥?

enter image description here

编辑:DDL和CHAR_LENGTH

CREATE TABLE PLU__ 
(
    PLU_NUM Varchar(16), 
    CAPTION Varchar(50), 
... 

enter image description here

+0

请出示表的DDL。 –

+1

在标准SQL中,比较值时会忽略尾随空格(或者如标准所指定的那样:在执行比较之前,较短的值用空格填充为较长值的长度)。 –

+0

@MarkRotteveel你的意思只是CHAR类型,而不是VARCHAR和文本BLOBS,不是吗? –

  1. string[16] - 存在火鸟没有这样的数据类型。有CHAR(16)VARCHAR(16)(和BLOB SUBTYPE TEXT,但这是不可能的)。所以你忽略了关于你的系统的一些关键点。你不用Firebird工作,但有一些未公开的中间层,那是没有人知道如何不透明或透明。

我怀疑你或你的系统选择CHAR数据类型,而不是VARCHAR所有的数据是正确的,以空格填充到最大。或者可能是列/表/数据库的COLLATION,以便尾随空格无关紧要。

此外,你可能是错的。您声称被选中的行确实包含尾随空白,但我没有看到它。例如,将CHAR_LENGTH(plu_num)添加到您的SELECT中的列中,看看有什么。

此外,如果plu_num是数字 - 它应该不是integerint64而不是文本?

  1. 屏幕底部显示“(NONE)”。我怀疑这是“连接字符集”。允许向后兼容20年前制作的节目,但今天它非常危险。您必须查阅系统文档,如何将连接字符集设置为URF-8或Windows-1250或其他有意义的内容。

  2. “我如何检查唯一的密钥,以便不包含尾随空格的密钥?”你没有。你不能可靠地做到这一点,因为不同的交易和不同的程序可以同时进行连接。你会检查它,确定你很清楚,但在你插入你的行之前 - 其他计算机也会插入它。在你的两个检查和插入命令之间,这种差距是不可能的,任何人都可以这样做。它被称为竞赛条件

您必须要求服务器执行检查。

例如,您必须在列对(store, plu_num)上引入UNIQUE CONSTRAINT。这样,服务器将拒绝在这些列中存储两个具有相同值的行,在同一个transaction中可见。

此外,具有空格的值甚至是正常的吗?将字段转换为整型数据类型并且安全。 或者,如果你想保持它的文本和非数字仍然可以

  1. 介绍CHECK CONSTRAINTtrim(plu_num) is not distinct from plu_num(或者,如果plu_num声明为NOT NULL列到服务器,然后trim(plu_num) = plu_num) 。这样服务器会拒绝在文本之前或之后用空格存储任何值。
  2. 的情况下的数据类型或列的排序规则,使有和没有尾随空格比较文本没有区别(在情况下,你不能改变的数据类型或归类),你可以尝试添加标记,就像('+' || trim(plu_num) || '+') = ('+' || plu_num || '+')

    1. 或者而不是CHECK CONSTRAINT,你可以主动删除这些位:设置新before update or insertTRIGGER在桌子上,那会不喜欢NEW.plu_num = TRIM(NEW.plu_num)
    2. 文档:

此外,经由http://www.translate.ru更有点冗长:

您还可以检查http://www.firebirdfaq.org/cat3/

此外,如果与非有效数据之前输入您介绍这些检查之前,你可能陷自己添加约束到现有表进入“不可恢复的备份”状态。您必须检查它,并且清理旧数据以遵守新引入的约束条件。


选项#4详细说明如下。这似乎是数据库设计的一个坏主意!每个人都应该不只是“让人们编辑号码删除尾随空白”,应该使数据库设计,这样便就没有任何数字与结尾的空白和就没有任何方式将它们插入到数据库中。

CREATE TABLE "_NEW_TABLE" (
    ID INTEGER NOT NULL, 
    TXT VARCHAR(10) 
); 

Select id, txt, '_'||txt||'_', char_length(txt) from "_NEW_TABLE" 

ID TXT CONCATENATION CHAR_LENGTH 
1 1 _1_ 1 
2 2 _2_ 1 
4 1 _1 _ 2 
5 2 _2 _ 2 
7 1 _ 1_ 2 
8 2 _ 2_ 2 


Select id, txt, '_'||txt||'_', char_length(txt) from "_NEW_TABLE" 
where txt = '2' 

ID TXT CONCATENATION CHAR_LENGTH 
2 2 _2_  1 
5 2 _2 _ 2 

Select id, txt, '_'||txt||'_', char_length(txt) from "_NEW_TABLE" 
where txt || '+' = '2+' -- WARNING - this PROHIBITS index use on txt column, if there is any 

ID TXT CONCATENATION CHAR_LENGTH 
2 2 _2_  1 

Select id, txt, '_'||txt||'_', char_length(txt) from "_NEW_TABLE" 
where txt = '2' and char_length(txt) = char_length('2') 
开始=> 开始=“4”>
+0

添加了DDL,你是否想说有没有办法做一个严格的字符串比较在SQL where子句? –

+0

@AntonDuzenko有 - 例如在我的回答 –

+0

@AntonDuzenko中查看#4,或者您可以在WHERE子句中检查'char_length'(如果有的话,选项#4将禁止在该列上使用索引)! –