string[16]
- такого типа данных в Firebird нет. Есть CHAR(16)
и VARCHAR(16)
(и BLOB SUBTYPE TEXT
, но тут маловероятно). Таким образом, вы опускаете некоторые важные моменты о вашей системе. Вы работаете не с Firebird, а с каким-то нераскрытым промежуточным слоем, то есть неизвестно насколько непрозрачным или прозрачным.
Я подозреваю, что вы или ваша система выбрали тип данных CHAR
вместо VARCHAR
, где все данные дополняются справа пробелом до максимума. ИЛИ, возможно, COLLATION
столбца/таблицы/базы данных таково, что конечные пробелы не имеют значения.
Кроме того, вы можете просто ошибаться. Вы утверждаете, что выбранная строка содержит пробел в конце, но я этого не вижу. Например, добавьте CHAR_LENGTH(plu_num)
к столбцам в вашем SELECT и посмотрите, что там.
Кроме того, если plu_num
является числом, не должно ли это быть integer
или int64
, а не текст?
Внизу вашего снимка экрана показано «(НЕТ)». Я подозреваю, что это «кодировка подключения». Это разрешено для обратной совместимости с программами, сделанными 20 лет назад, но сегодня это довольно опасно. Вы должны проконсультироваться с вашей системной документацией, как установить кодировку соединения на URF-8 или Windows-1250 или что-то значимое.
"Как проверить уникальный ключ, чтобы ключи с пробелами в конце не включались?" нет. Вы просто не можете сделать это надежно из-за разных транзакций и разных программ, выполняющих одновременные соединения. Вы проверите это, решите, что все ясно, но прямо перед тем, как вы вставите свою строку, какой-нибудь другой компьютер тоже вставит ее. Этот разрыв не может быть преодолен таким образом, между двумя вашими командами проверки и вставки - это может сделать и любой другой. Это называется условия гонки.
Вы должны попросить сервер сделать проверки.
Например, вам нужно ввести UNIQUE CONSTRAINT
в пару столбцов (store, plu_num)
. Таким образом, сервер отказался бы хранить две строки с одинаковыми значениями в этих столбцах, видимых в одном и том же transaction
.
Кроме того, нормально ли иметь значения с пробелами? Преобразуйте поле в целочисленный тип данных и будьте в безопасности. Или, если вы хотите сохранить его текстовым и нечисловым, вы все равно можете
- Введите
CHECK CONSTRAINT
, что trim(plu_num) is not distinct from plu_num
(или, если plu_num
объявлен серверу как столбец NOT NULL
, то trim(plu_num) = plu_num
). Таким образом, сервер отказался бы хранить любое значение с пробелами до или после текста.
В случае, если тип данных или сопоставление столбца не имеет значения для сравнения текстов с конечными пробелами и без них (и если вы не можете изменить этот тип данных или сопоставление), вы можете попробовать добавить токены, такие как ('+' || trim(plu_num) || '+') = ('+' || plu_num || '+')
- Или вместо этого
CHECK CONSTRAINT
вы можете предварительно удалить эти пробелы: установить новые before update or insert
TRIGGER
в таблице, что будет похоже на NEW.plu_num = TRIM(NEW.plu_num)
Документация:
Также через 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')
person
Arioch 'The
schedule
04.07.2017
CHAR
в Firebird. - person Mark Rotteveel   schedule 04.07.2017