-
Помню была такая тема. Почти что "святая война". Но тут столкнулся с проблемой, что пользователь упорно мне доказывает целесообразность данного момента в моих компонентах-наследниках TDataset.
Я стою на своем, что это разные сущности абсолютно. А он предлагает компромисс - ввести флаг и по желанию программиста, чтобы работало то так, а то эдак.
Самое плохое, что привел примеры програм, которые так и поступают. Например, pgAdminIII, DOA для Oracle, IBX для Interbase/Firebird...
Каковы мысли? Я понимаю, что это супротив стандарта. Но если рынок требует, может стоит?
-
Если сильно настаивает и готов за это дело заплатить - то пуркуа бы и не па?
-
> Ega23 © (01.07.08 15:10) [1]
А совесть куда деть? :)) Меня от одной мысли коробит. У меня ж отец военный. Не положено по уставу.
-
> А совесть куда деть?
отдельной строкой в смете :)
-
Тут ведь еще какой момент NULL <> NULL, а '' = ''. Ну и прочие вкусности. В том же запросе WHERE .. IS NULL супротив WHERE ... = ''
Опять же, если это так востребовано почему это не реализовано в серверной логике? Даже параметра такого нету.
-
> Отождествление пустой строки и NULL
У меня к тебе вопрос - а как ты их визуально различишь ?
-
Подожди. Речь о том, чтобы НА СЕРВЕРЕ подменить Null на ''? Или всё-таки на клиенте?
-
> а как ты их визуально различишь ?
а зачем? визуал - это последнее из применений
а остальные - сплошь автоматы
и геморроиться в проверкой нуллов, если мне это не надо, не хочется
-
Я не вижу ничего дурного в том, что если у тебя ftString - то при Null-значении показывать '', если ftInteger - то 0 и т.п.
На крайняк - ввести макроподстановку в свойство филда, типа при Null-значении писать '' или "Пусто" или "NULL".
Но - только для отображения.
-
Мало того, что я не понимаю, каков фактический смысл отличия "" от NULL с точки зрения предметной области, я еще и не понимаю, как их визуально отличать. Например, как отличать 0 от NULL я знаю, а вот со строками - тупик.
-
> pasha_golub © (01.07.08 15:07)
> Помню была такая тема. Почти что "святая война". Но тут
> столкнулся с проблемой, что пользователь упорно мне доказывает
> целесообразность данного момента в моих компонентах-наследниках
> TDataset.
Хм, а свойству asString как-то пофигу, что там null или строка нулевой длины...
-
> Игорь Шевченко © (01.07.08 15:34) [9]
> Мало того, что я не понимаю, каков фактический смысл отличия
> "" от NULL с точки зрения предметной области, я еще и не
> понимаю, как их визуально отличать.
Визуальность - дело последнее. Например, пустая строка это нейтральный элемент относительно операции конкатенации, как и 0 в случае сложения. Однако, если сделать 'string' || NULL, то получаем NULL.
Визуально, конечно, да. Пользователю один черт что пустое место, что надпись NULL
-
> Хм, а свойству asString как-то пофигу, что там null или
> строка нулевой длины...
>
И чё? TField.GetAsString : string; virtual;
Как хошь перекрыть можно.
-
> Я не вижу ничего дурного в том, что если у тебя ftString
> - то при Null-значении показывать '', если ftInteger - то
> 0 и т.п.
Со строками еще куда ни шло, а вот с числами... Поле Зарплата, например, то ли NULL - неизвестно или не начислено, или 0. :-)
-
pasha_golub © (01.07.08 15:39) [11]
> Визуальность - дело последнее. Например, пустая строка это
> нейтральный элемент относительно операции конкатенации,
> как и 0 в случае сложения. Однако, если сделать 'string'
> || NULL, то получаем NULL.
я@ora10> select 'Foo'||NULL from dual;
'FO
---
Foo
я@ora10>
Мне не верить своим глазам ?
-
> Поле Зарплата, например, то ли NULL - неизвестно или не
> начислено,
не определено.
-
Павель, вот никогда бы полю, отвечающему за деньги NULL бы не поставил. Ибо - Sum чему равно будет? :)
-
> пользователь упорно мне доказывает целесообразность данного
> момента
КЛИЕНТ ВСЕГДА ПРАВ!!!
-
> Ибо - Sum чему равно будет?
Все правильно - пока все слагаемы не известны, суммировать опасно.
А то получится 10 конфет каждому по 8 :)
-
> Мне не верить своим глазам ?
MSSQL 2000
Declare @x varchar(10), @y varchar(10)
Set @x=null; Set @y='foo'
Select @x + @y
--------------------
NULL
(1 row(s) affected)
-
> Все правильно - пока все слагаемы не известны, суммировать
> опасно.
Ну тот же MSSQL :
create table xxx(A int null)
insert into xxx(A) Values (default)
insert into xxx(A) Values (1)
insert into xxx(A) Values (2)
insert into xxx(A) Values (3)
insert into xxx(A) Values (4)
Select Sum(A) from xxx
drop table xxx
-----------
10
(1 row(s) affected)
Warning: Null value is eliminated by an aggregate or other SET operation.
-
Ega23 © (01.07.08 15:47) [19]
Я сильно извиняюсь, а в MSSQL пустая строка и NULL это одно и тоже, как и в Oracle ?
-
> Я сильно извиняюсь, а в MSSQL пустая строка и NULL это одно
> и тоже, как и в Oracle ?
>
Нет. Пустая строка <> NULL. И NULL<> пустому НД (IsEmpty).
-
Кстати, в oracle
я@ora10> create table xxx(A int null);
Table created.
я@ora10> insert into xxx(A) Values (null);
1 row created.
я@ora10> insert into xxx(A) Values (1);
1 row created.
я@ora10> insert into xxx(A) Values (2);
1 row created.
я@ora10> insert into xxx(A) Values (3);
1 row created.
я@ora10> insert into xxx(A) Values (4);
1 row created.
я@ora10> Select Sum(A) from xxx;
SUM(A)
----------
10
Но:
я@ora10> Select Sum(A+10) from xxx;
SUM(A+10)
----------
50
то есть, в случае A is NULL, A + 10 тоже NULL
-
> Нет. Пустая строка <> NULL. И NULL<> пустому НД (IsEmpty).
тогда пример ничего не показывает
-
> Select Sum(A) from xxx
Ну, спасибо хоть Warning выдал...
-
> тогда пример ничего не показывает
Почему? При конкатенации строк если один из операндов NULL - то и результат NULL. порядок операндов не важен.
В случае с числами - посложнее. по крайней мере, Warning выдаст.
ИМХО: сам использую null только в двух случаях:
1. Иерархические структуры (для определения корневого элемента)
2. При хранении метаданных (BLOB). И то не всегда.
-
Да, я напутал, агрегатные функции действительно обычно просто пропускают значения NULL, а в операциях приводят к NULL результат
-
> При конкатенации строк если один из операндов NULL - то
> и результат NULL. порядок операндов не важен.
а в оракле нет, именно пример с конкатенацией я и привел в [14]
в oracle пустая строка и NULL - это одно и то же. При конкатенации NULL себя ведет, как пустая строка. Вполне разумно. Мне представляется, что в Oracle тоже не понимали до конца, какое отличие с точки зрения предметной области имеют NULL и '', а главное - как их визуально отличать :)
-
> в oracle пустая строка и NULL - это одно и то же.
Однако. Не знал, что Оракловцы настолько смелы. Обычно это в стиле МС класть прибор на стандарты.
-
> Мне представляется, что в Oracle тоже не понимали до конца,
> какое отличие с точки зрения предметной области имеют NULL
> и '', а главное - как их визуально отличать :)
Да также, как и с PChar. p=nil и p^=''.
Т.е. в одном случае - вааще хзч. В другом - всё-таки пустая строка. :)
-
> Игорь Шевченко © (01.07.08 16:01) [28]
Никогда не сталкивался, просто интересно - а как в Оракл unique key отнесётся к нескольким пустым строкам ?
-
> McSimm © (01.07.08 16:09) [31]
> а как в Оракл unique key отнесётся к нескольким пустым строкам
> ?
Во, кстати, классный вопрос!
-
McSimm © (01.07.08 16:09) [31]
> а как в Оракл unique key отнесётся к нескольким пустым строкам
> ?
Проигнорирует. Значения NULL в UNIQUE (именно в UNIQUE) не попадают, на чем основано немало остроумных решений проблем.
Но, если ключ состоит из нескольких полей и одно может принимать значение NULL, то два набора с одинаковым значением одного поля и NULL другого поля вызовут нарушение уникальности.
pasha_golub © (01.07.08 16:08) [29]
> Однако. Не знал, что Оракловцы настолько смелы. Обычно это
> в стиле МС класть прибор на стандарты.
Оракл появился немного раньше стандартов.
-
никак. форинкеи допускают нулы, а юник нет
-
> Никогда не сталкивался, просто интересно - а как в Оракл
> unique key отнесётся к нескольким пустым строкам ?
>
ИМХО, также, как и везде - обматерит.
ЕМНИП, для MSSQL индекс допускается только в том случае, если есть только одно значение Null. Для первичного ключа - вообще не допускается. Для вторичного - можно много null (но он и не является индексом, только "кандидатом" на индекс).
-
> Например, pgAdminIII, DOA для Oracle, IBX для Interbase/Firebird...
Ну про pgAdminIII не знаю, а про IBX для Interbase/Firebird ты не прав, в IB/FB и соответственно,
в компонентах это абсолютно разные вещи. Так же как и в MS SQL, т.е. по стандарту.
Oracle поступает по своему, там NULL = '', по моему, обсуждалось много раз, на всех сайтах.
Иногда удобно, иногда нет. Для остальных типов данных (кроме строк) Oracle работает по стандарту.
-
Однако. Не знал, что Оракловцы настолько смелы. Обычно это в стиле МС класть прибор на стандарты.
Общий подход это использовать либо спец значения типов если они есть, или флаги нулов.
Пустая строка это как раз то спец значение строкового типа, которое позволяет обойтись без флагов.
-
> ЕМНИП, для MSSQL индекс допускается только в том случае,
> если есть только одно значение Null.
Был неправ:
UNIQUE constraints can be defined on columns that allow null values, whereas PRIMARY KEY constraints can be defined only on columns that do not allow null values.
-
Нда, опоздал немного с ответом.
-
Если пример
[23] дополнить:
я@ora10> create unique index yyy on xxx(a);
Index created.
я@ora10> select * from xxx order by a;
A
----------
1
2
3
4
я@ora10> insert into xxx values(NULL);
1 row created.
я@ora10> select * from xxx order by a;
A
----------
1
2
3
4
6 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 4016984797
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 78 | 4 (25)| 00:00:01 |
| 1 | SORT ORDER BY | | 6 | 78 | 4 (25)| 00:00:01 |
| 2 | TABLE ACCESS FULL| XXX | 6 | 78 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Видно, что индекс игнорируется, потому что есть значения NULL, а запрошены все записи.
но:
я@ora10>select * from xxx where a is not null order by a
A
----------
1
2
3
4
Execution Plan
----------------------------------------------------------
Plan hash value: 2441963755
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 52 | 1 (0)| 00:00:01 |
|* 1 | INDEX FULL SCAN | YYY | 4 | 52 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------
-
> atruhin1 (01.07.08 16:15) [36]
> а про IBX для Interbase/Firebird ты не прав, в IB/FB и
> соответственно,
> в компонентах это абсолютно разные вещи.
Прошу прощения. Я сам не проверял. Все со слов пользователя.
-
А еще один довод от пользователя.
CREATE TABLE ..(
somecol char(1) CHECK somecol in ('M', 'W')
)
И соответственно в таком виде NULL позволяется, а пользователь не может его вставить через грид или другой какой контрол.
-
> И соответственно в таком виде NULL позволяется
не позволяется. Он вызывает нарушение ограничения :)
-
Всякое бывает.
Другой какой-нибудь контрол обработает, к примеру, Ctrl-Del и отобразит [NULL]
-
somecol char(1) CHECK somecol in ('M', 'W')
А где "Ребёнок" и "Домашнее жЫвотное"? :)
-
> Игорь Шевченко © (01.07.08 16:26) [43]
>
> не позволяется. Он вызывает нарушение ограничения :)
Не знаю как в Оракле, но в Постгресе не вызовет
-
> McSimm © (01.07.08 16:28) [44]
> Другой какой-нибудь контрол обработает, к примеру, Ctrl-
> Del и отобразит [NULL]
И ведь не поспоришь.
> Ega23 © (01.07.08 16:30) [45]
> А где "Ребёнок" и "Домашнее жЫвотное"? :)
Не догадалсо. :) я обычно пишу M\F (male\female), однако есть еще люди которым ближе man\woman :)
-
Кстати, по поводу приведенного примера я чего еще задумался. Ведь char(1) должен состоять из одного символа и точка. Это ведь не varchar(1). То есть в таком случае было бы может и логично пустую строку возводить в статус NULL, однако в случае varchar религия имеет место быть.
-
> я обычно пишу M\F (male\female),
sometimes camel
> Это ведь не varchar(1).
varchar(1) тоже состоит из одного символа и точка. Из половины символа он состоять не может. В оракле так они даже хранятся одинаково char(1) и varchar(1)
-
> pasha_golub (01.07.2008 15:07:00) [0]
TDataset говоришь?
Так ничего не выйдет, пустая строка равна nil и никакой структуры строки. Не возможно представить строку по другому как пустое в Дельфи. В базе может и можно.
-
> pasha_golub (01.07.2008 15:18:04) [4]
А где тут TDataset?
При том это всего лишь особенность получается при присвоение значения и обратно никак, только если специально присвоить NULL.
А этим NULL <> NULL ты что хотел сказать?
-
> Ega23 (01.07.2008 15:20:06) [6]
В вопросе на клиенте, и при том для типа string
А дальше пошел какой то разброд, уже далекий от вопроса.
-
> Ega23 (01.07.2008 15:32:08) [8]
> ftString - то при Null-значении показывать ''
А это как, хочешь Дельфи переписать?
-
> sometimes camel
>
упалпацтул!!!
КЛАСС!!!! :)))))))))))))
-
> pasha_golub (01.07.2008 15:07:00) [0]
Кстати ты собираешься ограничиться только этими серверами? И где в них там TDataset
-
> Ega23 (01.07.2008 15:44:16) [16]
Так не все же архитекторы грамотные.
Кстати как насчет минуса? Тоже не так одназначно.
-
> Ega23 (01.07.2008 15:47:19) [19]
Ага значит все таки о конкретных серверах будем говорить, тогда посмотри ANSII настройки. В частности SET NULLS в БОЛ
-
> Игорь Шевченко (01.07.2008 15:48:21) [21]
Разные вещи, NULL соответствует определению ANSI если только поведение не изменено для ANSI настроек, пошли кое где на поводу старого матобоеспечения (FoxPro например, а это у них основной носитель для импорта/экспорта).
Про Oracle молчим, Oracle и стандарты, это рок против наркотиков.
-
> Игорь Шевченко (01.07.2008 16:01:28) [28]
Твое предположение верно, может тебе попадались обсуждения с разработчиками по этому поводу.
-
> pasha_golub (01.07.2008 16:08:29) [29]
Видишь ли МС не кладет, а позволяет управлять этим, а насколько я помню Оракл именно кладет. При том вроде и не последовательны.
-
> McSimm (01.07.2008 16:09:31) [31]
Пустым ты что в данном случае считаешь, если '' то по стандарту одну можно. А если NULL то по стандарту ни одно, поскольку NULL это не определено, то оно и не может представлять собой конкретную строку, а вот пустая строка может.
-
> Игорь Шевченко (01.07.2008 16:13:33) [33]
> Оракл появился немного раньше стандартов.
И вырос в такого монстра, что плевал на всех, он сам себе стандарт.
-
> atruhin1 (01.07.2008 16:15:36) [36]
> Иногда удобно, иногда нет.
Вот это не должно быть основанием, поскольку результаты не гарантируются, не пройдет даже тестов.
-
> Пустым ты что в данном случае считаешь, если '' то по стандарту
> одну можно. А если NULL то по стандарту ни одно, поскольку
> NULL это не определено
Так вопрос про Оракл был, где '' и NULL суть одно.
Насчет стандарта - не совсем понял. Unique key, насколько я с ними сталкивался, позволяет хранить NULL в любом количестве.
-
> Unique key, насколько я с ними сталкивался, позволяет хранить
> NULL в любом количестве.
Короче, была какая-то фигня с Null. То ли с FTS, то ли с индексом...
В смысле, что только одно значение null в столбце на всю таблицу.
-
Anatoly Podgoretsky © (01.07.08 16:55) [62]
> И вырос в такого монстра, что плевал на всех, он сам себе
> стандарт.
Насколько мне известно, стандарту целиком и полностью не соответствует ни одна СУБД. У каждой есть свои расширения, отходящие от стандарта.
Кстати, сам Оракл пишет в документации:
"Oracle Database currently treats a character value with a length of zero as null. However, this may not continue to be true in future releases, and Oracle recommends that you do not treat empty strings the same as nulls."
-
то оно и не может представлять собой конкретную строку, а вот пустая строка может.
Если пустая строка может представлять конкретную строку ("равноправное" значение строкового типа), то тогда было бы возможно определить сколько именно таких значений содержится в этом посте.
А этого никто определить не сможет.
-
> сколько именно таких значений содержится в этом посте.
Я могу это определить.
Этот пост представляет собой запись из нескольких полей (некоторые отображаются, некоторые нет). Из отображаемых - одно поле представляет собой пустую строку.
А дробить одно поле - некорректно. Или придется считать количество нулей в числе 17.
-
Я могу это определить.
Допустим.
Определил, что из там 10.
А я утверждаю что изх там 1000.
Как определить кто прав?
-
> Как определить кто прав?
гм... я даже теряюсь... при таком подходе остается только назначить незаинтересованных арбитров и спросить кому они больше верят :)
Я даже могу предоставить саму запись на рассмотрение (хотя ее и так видно)
name: 'Поросенок Винни-Пух',
email: '',
ip: '**.***.**.***'
и т.д.
-
есть еще вариант, спросить у perl
# smth like this
foreach (keys %fields) {
$count++ if ($REC{$_} eq '');
}
-
ну зачем же отмахиваться от простого вопроса?
есть два строковых литерала, один пустой;
я с помошью нескольких конкатенаций делаю из них итоговую строку.
вопрос: определить по итоговой строке сколько раз я в нее вставил пустой литерал.
-
> Поросенок Винни-Пух © (01.07.08 17:37) [67]
> Если пустая строка может представлять конкретную строку
> ("равноправное" значение строкового типа), то тогда было
> бы возможно определить сколько именно таких значений содержится
> в этом посте.
Нелогично размышляете. Я уже писал что пустая строка есть инвариант по отношению к операции конкатенации. Можно провести паралели с каноническим разложением числа на множители (сорри если коряво звучит, учил на украинском), коее имеет вид a = p1^n1*p2^n2...*pk^nk*E, где pi - простые числа неравные 1.
-
> ну зачем же отмахиваться от простого вопроса?
> есть два строковых литерала, один пустой;
> я с помошью нескольких конкатенаций делаю из них итоговую
> строку.
> вопрос: определить по итоговой строке сколько раз я в нее
> вставил пустой литерал.
Я уже писал про количество нулей в числе 17.
-
> Поросенок Винни-Пух © (01.07.08 18:02) [72]
> есть два строковых литерала, один пустой;
> я с помошью нескольких конкатенаций делаю из них итоговую
> строку.
> вопрос: определить по итоговой строке сколько раз я в нее
> вставил пустой литерал.
Есть два слагаемых, один из них 0. Я с помощью некоторых операций сложения делаю из них сумму.
Вопрос: определить по итоговой сумме сколько раз я прибавил 0
-
Поле содержит одно значение. Можно считать сколько значений содержит запись или выборка. Какой смысл считать количество значений в одном поле ? (то же - в одной переменной) ?
-
Я уже писал про количество нулей в числе 17.
не надо путать публику.
было сказано, что пустая строка - это точно такое же значение строкового типа, как и любая другая строка.
Так что это за значение такое, если его нельзя обнаружить и посчитать?
-
И, кстати о конкатенациях, сколько значений "АА" содержится в строке "АААА" - два или три ?
-
> пустая строка - это точно такое же значение строкового типа,
> как и любая другая строка.
Равно как и 0 мало отличается от любого другого числового значения.
-
> И, кстати о конкатенациях, сколько значений "АА" содержится
> в строке "АААА" - два или три ?
Правильный ответ - ни одного
-
И, кстати о конкатенациях, сколько значений "АА" содержится в строке "АААА" - два или три ?
Если строка получена конкатенацией двух литералов 'AA', то там их две.
А я предлагаю определить то же самое для строки 'AAAA', полученной конкатенацией '' и 'A'
-
I've given up... At least until you've counted zeroes in the number 17 that is the sum of numbers 0 and 1...
-
не нравится конкатенация?
могу по другому:
открываем между собой тсп соединение, или создаем поток.
я делаю туда икс раз writebuff с пустой строкой, а ты считаешь сколько раз я это сделал.
и не вижу проблем. это же такое же "равноправное" значение как и все остальные строки.
-
I've given up... At least until you've counted zeroes in the number 17 that is the sum of numbers 0 and 1...
сколько раз был записан в поток нулевой байт или нулевой word, dword etc я могу определить. а вот определи сколько раз я записал на носитель пустую строку.
слабо?
-
> и не вижу проблем
Я вижу, но это офтопик.
Контейнер для значения какого-либо типа это переменная или поле базы данных.
Количество значений в одном контейнере всегда одно.
Последняя попытка, чесслово :)
Пишем в буфер обычные равноправные строки "А" и "АА" и считаем.
-
нет, уловки не прокатят. :)
в случае с буфером и "A" и "AA" по крайней мере можно определить, что хотя бы одно значение было записано в буфер.
с пустой строкой это не пройдет.
просто потому, что это никакое не "равноправное" значение строкового типа, а совершенно особенное. и его-то и использует оракл для строкового нула.
-
А при Join - что должно приходить?
-
> Поросенок Винни-Пух © (01.07.08 19:13) [86]
Почему Оракл не использует 0 для нулла?
-
> Поросенок Винни-Пух (01.07.2008 17:37:07) [67]
Не понял, что именно ты имеешь в виду, но что ты скажешь про это Count(*) - Count(Field)
-
> в случае с буфером и "A" и "AA" по крайней мере можно определить,
> что хотя бы одно значение было записано в буфер.
Понятно, меняем условия на ходу. Смысла все меньше.
А я хочу определять хотя бы два.
> никакое не "равноправное" значение строкового типа, а совершенно
> особенное. и его-то и использует оракл для строкового нула.
Абсолютно любое значение можно назвать особенным.
Любое значение можно было бы выбрать для индикации NULL, но пустая строка больше всех подходит для этого.
С тем же успехом можно доказывать уникальность значения "-1"
-
> McSimm (01.07.2008 18:13:18) [78]
Если про конкатенацию, то возможно ни одного.
А зачем пытаться делать обратно из фарша корову?
-
Почему Оракл не использует 0 для нулла?
Потому что это действительно равноправное целочисленное значение среди других значений целых
-
> Поросенок Винни-Пух (01.07.2008 19:13:26) [86]
Ошибаешься, для строки АААА определить сколько раз было записано АА невозможно, это невозможно даже строки АА
И никакого отношения к NULL и пустым строкам это не имеет отношения, это совершенно другой закон математики. Вроде бы транзитивность, не помню точное название термина.
Я для тебя дам несложную задачку - есть число, получено суммой трех чисел, каждое из которых больше нуля. Результат равен 1234567890. Чему равны A B C, Я тебе даже упрощаю задачу, я тебе назову одно из них, это два, а ты назови оставшие два. Попробуй сделать корову.
-
Ошибаешься, для строки АААА определить сколько раз было записано АА невозможно, это невозможно даже строки АА
Извращенный пример.
Я же согласился, что с конкатенацией пример не очень удачен.
Вот пример удачный.
Берем двух экспериментаторов и две совершенно детерминированные строки. Обе известны обеим участникам эксперимента заранее.
Один делает writebuff, другой определяет сколько раз было записано значение в поток.
одна строка пустая, другая нет.