Почему я не могу ввести значение NULL, используя числовой тип или тип даты в Postgresql?

Я делаю небольшое приложение для работы, и оно включает в себя форму. Когда человек, использующий форму, не помещает значение в тип данных «числовой» (скажем, PIN-код) или даже дату в одном из моих полей типа «дата» (скажем, его годовщину), он возвращает меня с такими ошибками:

Тип ошибки — тип ошибки _Microsoft OLE DB Provider для драйверов ODBC (0x80004005)_ ОШИБКА: неверный синтаксис ввода для числового типа: ""; Ошибка при выполнении запроса

Тип ошибки — тип ошибки _Microsoft OLE DB Provider для драйверов ODBC (0x80004005)_ ОШИБКА: синтаксическая ошибка в или около ")"; Ошибка при выполнении запроса

Таким образом, кажется, что когда человек, использующий форму, ничего не вводит, она возвращает строку «пусто», то есть «». Почему числовой тип и тип данных не могут прочитать это как запись NULL? Эти поля не являются обязательными, поэтому иногда мне нужно, чтобы они были пустыми.

Как я могу сделать это возможным? Это способ продолжать использовать «числовой» и «дата» тип, чтобы, когда пользователь ничего не вводит в эти поля, таблица заполнялась пустым регистром вместо того, чтобы выдавать мне эту ошибку?

Вот мой оператор sql:

trsConn.EXECUTE "INSERT INTO ""TRS"".employeetbl ( "& _
  """firstName"", " & _  
  """lastName"" , " & _  
  """detContract"", " & _  
  "sle, " & _  
  """posNumber"" "& _  
  ") VALUES (" & _  
  "'" & Request.Form("empFirst") & "', " & _**  
  "'" & Replace(Request.Form("empLast"), "'", "`") & "', " & _  
  "'" & Request.Form("dateContract") & "', " & _
  "'" & Request.Form("sle") & "', " & _  
  "'" & Request.Form("posNum") & "');"  

(PosNum и dateContract имеют тип «числовой» и «дата» соответственно.

Большое спасибо за помощь. С нетерпением жду, что вы, гении, скажете.


person Vince.CRA    schedule 14.08.2012    source источник
comment
Ух ты. Поддерживает ли классический ASP заполнители или подготовленные операторы? Я подозреваю, что одна проблема заключается в том, что он интерполирует данные, поэтому они заканчиваются как .. VALUES (.., 'NULL', ..), а не .. VALUES (.., NULL, ..), как должно быть.   -  person    schedule 14.08.2012
comment
Кроме того, почему posNum использует (забавная одинарная кавычка, что неверно), а другие используют ' (апостроф, что правильно)? Можете ли вы ввести любое значение для posNum? (То есть название является отвлекающим маневром?)   -  person    schedule 14.08.2012
comment
Это классическое «не то же самое, что NULL». NULL никогда ничему не равен, и его нельзя ничем заменить (ну, я не могу сказать никогда — Oracle уже много лет является исключением). Если вы хотите назначить NULL, назначьте NULL. Если вы хотите узнать, является ли столбец NULL, используйте IS NULL; у них есть IsNull() и Coalesce() специально для работы со значениями NULL - поэтому у них есть специальные функции и оператор для проверки. NULL ‹› ничего другого и ничего больше = NULL.   -  person Ken White    schedule 14.08.2012
comment
@pst: я почти уверен, что он использует '', а не 'NULL', где он должен использовать только буквальное NULL.   -  person mu is too short    schedule 14.08.2012
comment
@muistooshort Это имеет смысл. К счастью, мне никогда не приходилось иметь дело с vbscript/ASP Classic.. Меня интересуют последние кавычки. :)   -  person    schedule 14.08.2012
comment
Кстати, ASP, использующий классические драйверы SQL, поддерживает подготовленные операторы: that-prevents-sql-injection" title="как я могу сделать подготовленный оператор в классическом asp, который предотвращает внедрение sql"> stackoverflow.com/questions/8538979/. Винс, пожалуйста, рассмотрите возможность использования подготовленных утверждений для удобочитаемости, для здравомыслия всех вокруг вас и для таблиц Poor Bobby Tables xkcd.com/327   -  person JayC    schedule 14.08.2012


Ответы (1)


Концепция NULL в SQL довольно запутанно и непоследовательно ... но очень ясно, что '' отличается от NULL.

'' не NULL, это '', пустая строка. Вы не можете преобразовать его в дату, число и т. д.:

regress=# SELECT CAST('' AS DATE);
ERROR:  invalid input syntax for type date: ""
LINE 1: SELECT CAST('' AS DATE);
                    ^
regress=# SELECT CAST('' AS NUMERIC);
ERROR:  invalid input syntax for type numeric: ""
LINE 1: SELECT CAST('' AS NUMERIC);
                    ^

Некоторые продукты, особенно Microsoft Access и старые версии MySQL, в этом вопросе запутались. NULL — NULL, '' — пустая строка; это не одно и то же. Вы не можете преобразовать одно в другое.

Таким образом, кажется, что когда человек, использующий форму, ничего не вводит, она возвращает строку «пусто», то есть «». Почему числовой тип и тип данных не могут прочитать это как запись NULL? Эти поля не являются обязательными, поэтому иногда мне нужно, чтобы они были пустыми.

Это работа вашего приложения. Когда ваше приложение увидит пустую строку в поле формы для числа, даты или чего-то подобного, оно должно отправить в базу данных NULL, а не ''. Обычно это рутинная часть преобразования данных из пользовательского ввода перед их передачей в базу данных. Выполнение такого преобразования жизненно важно; вы никогда не должны просто отправлять значения от пользователя прямо в базу данных.

Быстрый поиск показывает, что asp classic использует null или undefined в качестве нулевых значений; вы должны иметь возможность передавать их в свои подготовленные операторы, когда что-то равно нулю.

Тот факт, что вы получаете синтаксическую ошибку после ошибки о '', предполагает, что вы строите свои операторы SQL в виде строк, а не используете подготовленные операторы с заполнителями. (Спасибо JayC за ссылку на вопрос SO). Это требует инъекции SQL; другими словами, ваше приложение критически небезопасно. Представьте, что произойдет, если пользователь введет «дату»:

2012-01-01'); DROP SCHEMA public;--

и ваше приложение с радостью превращает это в

INSERT INTO sometable (blah, blah, blah) VALUES (1, 2, DATE '2012-01-01'); DROP SCHEMA public;--');

Затем DROP SCHEMA весело запускается, и упс, шлепок, вот и ваша база данных. Это просто самый тупой и самый простой вид атаки SQL-инъекцией.

person Craig Ringer    schedule 14.08.2012
comment
Большое спасибо за это Крэйг! Все, что открыло мне глаза, это действительно ценно. Кроме того, я понимаю, что мое приложение небезопасно, но оно все еще находится в разработке, и никто, кроме меня, не имеет к нему доступа. Он также не будет доступен через Интернет, так как его пользователи будут приходить с интранет-страниц моего агентства. Еще раз спасибо! - person Vince.CRA; 15.08.2012
comment
@Vince.CRA IMO, лучшее время, чтобы сделать его безопасным, когда вы его пишете, с самого начала. Безопасность — это не надстройка после того, как вы закончите, вам нужно подумать об этом при проектировании, выборе инструментов, прямо перед развертыванием, если вы хотите сделать это смутно правильно. Что касается отсутствия в Интернете, конечно, поверхность атаки меньше, но достаточно одного любопытного/недовольного сотрудника (или неправильно настроенного прокси-сервера). Существуют инструменты, которые позволяют каждому использовать простые уязвимости SQL-инъекций. - person Craig Ringer; 16.08.2012
comment
@Vince.CRA Кроме того, серьезно, вы разрабатываете новое приложение в классическом ASP? Это... интересное... решение. Как это будет поддерживать? - person Craig Ringer; 16.08.2012