Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Сюрприз при использовании ADO + MS SQL + пустой параметр ftString


И. Павел ©   (2010-08-31 11:26:00) 

Здравствуйте.

Наткнулся на странный результат выполнения запроса, с использованием пустого строкового параметра в MS SQL SERVER 2005. Вот такой код:
ADODS.Active := false;
ADODS.CommandText := 'SELECT … FROM USERLIST.dbo.UserInf WHERE login=:PLogin AND password= :PPassword';
ADODS.Parameters.ParseSQL(ADODS.CommandText, true);
ADODS.Parameters.ParamByName('PLogin').Value := login;
ADODS.Parameters.ParamByName('PPassword').Value := password;
ADODS.Open;

В случае если пароль пустой (т.е. password = ''), возникает ошибка (EOleException):
'The data types varchar and text are incompatible in the equal to operator'.

То есть SQL SERVER почему-то считает, что пустой параметр типа ftString имеет тип Text.
Эта же ошибка возникает, если вручную задавать DataType и Direction параметра.

Поле “password” имеет тип “varchar(50)”.

А если закомментировать строчку:
ADODS.Parameters.ParseSQL(ADODS.CommandText, true)
т.е. предоставить SQL Server и ADO подготавливать параметры самостоятельно, то все работает нормально, в том числе и при пустом пароле.

Методом тыка выяснил, что ошибка возникает из-за того, что при пустом пароле операция
ADODS.Parameters.ParamByName('PPassword').Value := '';
не меняет свойство Size для параметра, оставляя его равным -1. Код:
ADODS.Active := false;
ADODS.CommandText := 'SELECT … FROM USERLIST.dbo.UserInf WHERE login=:PLogin AND password= :PPassword';
ADODS.Parameters.ParseSQL(ADODS.CommandText, true);
ADODS.Parameters.ParamByName('PLogin').Value := login;
ADODS.Parameters.ParamByName('PPassword').Value := 1;
ADODS.Parameters.ParamByName('PPassword').Value := password;
ADODS.Open;

Работает. Но выглядит так себе, и, скорее всего, может вызвать еще какие-нибудь ошибки.

Подскажите, пожалуйста, как наиболее правильно работать с параметрами в ADODataSet и ADOCommand (ну и ADOQuery, т.к. в старых проектах я использовал его)? В частности: насколько правильно полагаться на автоматический “ParseSQL” и определение типа параметра? Если можно, то прямо пример, начиная от ADODS.Active := false.


PS: в access такой ошибки не возникает.
PPS: везет же мне на такие штуки… Максимальная отрицательная константа, проблема с параметрами в join в Access, время от времени не загружающийся реестр, теперь вот это… У всех так, или это у меня карма низкая?:)

Заранее спасибо.


Anatoly Podgoretsky   (2010-08-31 12:57:00) [1]

> И. Павел  (31.08.2010 12:54:10)  [10]

Но и в БДЕ он рекомендовался к применению только в редких случаях.


И. Павел   (2010-08-31 12:54:00) [2]

> ParseSQL имел смысл в БДЕ

Спасибо. Запомню на всякий случай. Хотя последний раз с БДЕ работал еще в институте.


И. Павел   (2010-08-31 12:53:00) [3]

> Если ошибки про несуществование параметра не возникает,
> то ессно писать именно так. На кой хрен еще раз парсить.

Спасибо. Тогда буду писать так.


Palladin   (2010-08-31 12:52:00) [4]


> Если да, то буду теперь писать так.

Если ошибки про несуществование параметра не возникает, то ессно писать именно так. На кой хрен еще раз парсить.


Anatoly Podgoretsky   (2010-08-31 12:52:00) [5]

> И. Павел  (31.08.2010 12:44:06)  [6]

ParseSQL имел смысл в БДЕ


И. Павел   (2010-08-31 12:44:00) [6]

> Так чего же ты мучишься?

Просто часто встречаю ParseSQL в разных статьях и на форумах, вот и подумал, что лучше использовать его. А оказалось - что это привело к тому, что тип параметра не совпадает с DataType.

Подскажите, пожалуйста, создание запроса с параметрами таким образом правильно:
ADODS.Active := false;
ADODS.CommandText := 'SELECT … FROM USERLIST.dbo.UserInf WHERE login=:PLogin AND password= :PPassword';
ADODS.Parameters.ParamByName('PLogin').Value := login;
ADODS.Parameters.ParamByName('PPassword').Value := password;
ADODS.Open;
Если да, то буду теперь писать так.


> Этого нам не достаточно

Вот все, что я нашел по полю "password", если нужно что-то еще - напишите:

Name - password
Data Type - varchar
System Type - varchar
Primary key - False
Allow nulls - False
Is Computed - False
Computed Text -
Identity - False
Identity seed - 0
Identity increment - 0
Default Binding
Default Schema
Rule
Rule Schema
Length - 50
Collation - Cyrillic_General_CI_AS
Numeric precision - 0
Numeric scale - 0
XML Schema Namespace -
XML Schema Namespace schema
Not for replication - False
Full text - False
ANSI Padding Status - True


Anatoly Podgoretsky   (2010-08-31 12:04:00) [7]


> Поле “password” имеет тип “varchar(50)”.

Этого нам не достаточно

> т.е. предоставить SQL Server и ADO подготавливать параметры
> самостоятельно, то все работает нормально, в том числе и
> при пустом пароле.

Так чего же ты мучишься?


И. Павел   (2010-08-31 11:49:00) [8]


> у тебя скорее всего NVarChar тип поля в таблице

Я перепроверил - тип именно varchar(50).


> я после парсинга сам в ручную назначал DataType в ftString
> и потом присваивал значение

Код:
 ADODS.Active := false;
 ADODS.CommandText := 'SELECT login, password, cabinet, log_del, ReportType, type FROM USERLIST.dbo.UserInf WHERE login=:PLogin AND password= :PPassword';
 ADODS.Parameters.ParseSQL(ADODS.CommandText, true);
 ADODS.Parameters.ParamByName('PLogin').DataType := ftString;
 ADODS.Parameters.ParamByName('PLogin').Value := login;
 ADODS.Parameters.ParamByName('PPassword').DataType := ftString;
 ADODS.Parameters.ParamByName('PPassword').Value := password;
 ADODS.Open;

У меня возвращает ту же ошибку.

Я попробовал сменить тип поля "password" на text, ошибка приняла вид:
'The data types text and varchar are incompatible in the equal to operator'.
тоесть теперь параметр воспринимается как varchar :)


Palladin   (2010-08-31 11:32:00) [9]

у тебя скорее всего NVarChar тип поля в таблице


Palladin   (2010-08-31 11:31:00) [10]


> То есть SQL SERVER почему-то считает, что пустой параметр
> типа ftString имеет тип Text.

он не ftString, выведи после
ADODS.Parameters.ParseSQL(ADODS.CommandText, true);

ADODS.Parameters.ParamByName('PLogin').DataType

я после парсинга сам в ручную назначал DataType в ftString и потом присваивал значение... есть такой косяк...


И. Павел   (2010-08-31 11:27:00) [11]

Извиняюсь, я опечатался. Не

> ADODS.Parameters.ParamByName('PPassword').Value := 1;

а

> ADODS.Parameters.ParamByName('PPassword').Size := 1;


Наверх

Титульная страница Поиск, карта сайта Написать письмо