Delphi: "объект параметра неправильно определен. Была представлена непоследовательная или неполная информация."
Это функция, которая делает следующее:
- создайте случайный токен с длиной 8
- вставьте этот токен в базу данных
Если у пользователя уже есть токен, обновите его.
Если у пользователя нет токена, вставьте его.
procedure createToken(BenuNr: integer);
var
AQ_Query: TADOQuery;
strToken: string;
intZaehler: integer;
const cCharSet: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
begin
//Random String as Token
SetLength(strToken, 8);
for intZaehler := 1 to 8 do
begin
strToken[intZaehler] := cCharSet[1+Random(Length(cCharSet))];
end;
//Inserts the Token into the Database
with AQ_Query do
begin
try
AQ_Query := TADOQuery.Create(nil);
ConnectionString := strConnectionString;
SQL.Text := 'if EXISTS(select * from TOKN where BENU_NR = :paramBenu_NR) begin update TOKN set TOKEN = :paramTOKEN where BENU_NR = :paramBenu_NR end else insert into TOKN (BENU_NR, TOKEN) values (:paramBENU_NR,:paramTOKEN)';
Prepared := true;
Parameters.ParamByName('paramBENU_NR').DataType := ftInteger;
Parameters.ParamByName('paramTOKEN').DataType := ftString;
Parameters.ParamByName('paramBENU_NR').Value := BenuNr;
Parameters.ParamByName('paramTOKEN').Value := strToken;
ExecSQL; //<< Exception as stated in the title
finally
Free;
end;
end;
end;
выполнение этого вызывает у меня исключение, как указано в заголовке. Я вырежьте приведенный выше пример и вуаля: больше никаких исключений. К сожалению, я не понимаю, почему?
procedure createToken();
var
AQ_Query: TADOQuery;
strToken: string;
intZaehler: integer;
const cCharSet: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
begin
//Random String as Token
SetLength(strToken, 8);
for intZaehler := 1 to 8 do
begin
strToken[intZaehler] := cCharSet[1+Random(Length(cCharSet))];
end;
//Inserts the Token into the Database
with AQ_Query do
begin
try
AQ_Query := TADOQuery.Create(nil);
ConnectionString := strConnectionString;
SQL.Text := 'update TOKN set TOKEN = :paramTOKEN where BENU_NR = 1';
Prepared := true;
Parameters.ParamByName('paramTOKEN').DataType := ftString;
Parameters.ParamByName('paramTOKEN').Value := strToken;
ExecSQL; //<< No more exception
finally
Free;
end;
end;
end;
Кажется, что на SQL разрешен только 1 параметр. Я использую Delphi 7 и MSSQL Server 2005
есть идеи, как исправить первый блок кода, чтобы он работал?
8 ответов
чтобы сделать эту работу вы должны использовать каждый параметр только один раз в условие SQL. Чтобы использовать один и тот же параметр более одного раза, просто объявите его с новым именем. Я не знаю, почему это так, но я знаю, что это может быть очень раздражает.
у меня была возможность попробовать это с компилятором :) я должен установить его дома когда-нибудь.
в то время как я все еще нахожу ваше использование с необычным, он, похоже, работает нормально.
Я видел ошибку, которую вы получаете в нескольких случаях:
- попытка выполнить более одного запроса против соединения сразу (из-за резьбы или таймера + processMessages)
- С TADOStoredProc, когда ProcedureName неверно
- иногда, если ADO не может проанализировать запрос - не может проверить это без вашей схемы БД.
обратите внимание, что в SQL Server Нет необходимости явно определять тип параметра. Они автоматически назначаются событием OnChanged, прикрепленным к объекту SQL TStringList.
в результате лучше всего либо назначить SQL.Свойство Text (как и вы), или при использовании .Добавить ('SELECT ...'), использовать SQL.BeginUpdate / SQL.Пара EndUpdate.
Оригинал ответ:
with AQ_Query do
begin
try
AQ_Query := TADOQuery.Create(nil);
ConnectionString := strConnectionString;
хотя это, кажется, работает, кажется немного странным ссылаться на объект, прежде чем создавать его экземпляр.
aq_query должен быть создан перед оператором with:
AQ_Query := TADOQuery.Create(nil);
with AQ_Query do
begin
try
ConnectionString := strConnectionString;
еще лучше не использовать С
пока эта ошибка является сложной задачей, вы можете диагностировать ее достаточно, чтобы увидеть, что ваш запрос является допустимым. Проблема в ваших параметрах. Лучший способ найти истинную проблему - это трассировка SQL Server Profiler вашей базы данных при поступлении запроса. Он покажет вам, как были интерпретированы параметры. Скопируйте этот запрос в текстовый редактор, чтобы узнать, в чем ваша проблема.
Если вы не можете использовать SQL Server Profiler, вы должны просто вывести значения "BenuNr" и " strToken" на экран или консоль, чтобы вы могли действительно видеть, что вы передаете в качестве параметров.
до сих пор я не исправил проблему.
но я думаю, что проблема лежит где-то внутри параметров и как к ним обращаются. Компилятор выбирает их по индексу, а не по имени, как я предполагал.
присмотревшись к компоненту TADOQuery в OI (особенно в разделе TParameters), вы можете увидеть, что индексы.
в конце концов это, вероятно, необходимо сначала добавить параметр, назначить ему имя, а затем вставить значение или что-то еще вроде этого.
выключите подготовку. Установите prepared=False для компонента ADO. Похоже, что сервер видит его до того, как оба параметра существуют, и готовит (компилирует) его. Когда вы выполняете его с двумя параметрами, список param не соответствует подготовленному оператору.
Оуч. Вы просто попали в то, что наш системный архитектор на работе называет "худшей ошибкой". Это довольно общая ошибка, и может означать все что угодно. Но я только когда-либо видел его на инструкциях INSERT, поэтому попробуйте посмотреть там. Это вызвано определением, что ADO каким-то образом не соответствует схеме базы данных.
попробуйте сократить запрос, чтобы сделать только вставку и использовать SQL profiler, включенный в SQL Management Studio, чтобы посмотреть, что делает ADO, когда он запускает его. Скорее всего, он запросит структуру вашей таблицы, сравните ее со структурой вашего оператора и в конечном итоге не понравится то, что он найдет, и никогда не отправит команду INSERT в базу данных.
убедитесь, что у вас есть правильные типы данных в полях, и что вы можете успешно выполнить вставку в таблицу, используя только эти два значения. Это может не сработать-это is худшая ошибка когда-либо, в конце концов, но это должно дать вам отправную точка.
вам не нужно указывать DataType
. После успешного вызова Prepare;
параметры должны быть настроены правильно, на основе определения таблицы сервера.
Я предполагаю, что, назначив DataType
, параметр, вероятно, сброшен, и некоторая информация отсутствует, например,ParamType
должно быть ptInput
но сбрасывается до ptUnknown
или что-то подобное.
Попробуйте удалить те строки, где вы установили тип данных, и посмотреть, поможет ли это.
для меня эта ошибка произошла без параметров, когда (в противном случае полностью допустимая) инструкция SQL содержала литеральное значение varchar с двоеточием (:) внутри цитируемого подтекста. Е. Г.
UPDATE ... SET myfield = 'foo " :bar "'
решением может быть переключение на параметры из уродливых встроенных литералов. Я еще не нашел другого подходящего обходного пути.