2015-01-17 5 views
1

Я хочу вставить запись в таблицу базы данных (сайт) с помощью процедуры с параметрами. Код SQL был протестирован в workbench mysql и работает правильно, чтобы вставить новые данные. Тем не менее, с delphi я получаю «Синтаксическую ошибку SQL около [вставить целую строку кода здесь]». Мне было интересно, может ли кто-нибудь из вас сказать мне, где я ошибаюсь. Еще раз спасибо.Вставить в синтаксическую ошибку SQL delphi

procedure TNewWebsite.InsertData(WID, D, T, Wh, Dr, Od, Rd, Rc, Pm, OStat, Cstat, Rstat, N, U1, P1, P2, PStat, CID : string); 
    begin 
    WebsiteTable.WebsiteQuery.SQL.Add('INSERT INTO website VALUES ('+WID+', '''+D+''', '''+T+''', '''+Wh+''', '''+D+''', '''+Od+''', '''+Rd+''', '+Rc+', '''+Pm+''', '+Ostat+', '+Cstat+', '''+Rstat+''', '''+N+''', '''+U1+''', '''+P1+''', '''+P2+''', '+Pstat+', '+CID+';)'); 
    WebsiteTable.WebsiteQuery.Open; 
end; 
+1

Пожалуйста, распечатайте результат выражения создания инструкции (то есть созданной строки SQL), и вы почти наверняка сразу увидите проблему. –

ответ

5

У вас довольно много проблем в коде.

A) Не преувеличивайте с параметрами функции, если у вас много переменных, соберите их в записи или классе в зависимости от ваших потребностей.

B) Ваш SQL-код уязвим для SQL-инъекции. Вы, наверное, никогда не слышали о SQL-инъекции, пожалуйста, Google или прочитайте это really good answer. Решение против SQL-инъекции - использовать параметры (см. Пример моего кода). Дополнительный бонус заключается в том, что ваш оператор SQL будет читабельным человеком и меньше подвержен ошибкам.

C) Функция Open используется только для запросов, возвращающих набор результатов, например SELECT. Для операторов INSERT, DELETE и UPDATE вам необходимо использовать функцию ExecSQL.

Sanitized код:

interface 

type 
    TMyDataRecord = record 
    WID : String; 
    D : String; 
    T : String; 
    Wh : String; 
    Dr : String; 
    Od : String; 
    Rd : String; 
    Rc : String; 
    Pm : String; 
    OStat : String; 
    Cstat : String; 
    Rstat : String; 
    N : String; 
    U1 : String; 
    P1 : String; 
    P2 : String; 
    PStat : String; 
    CID : String; 
    end; 
... 
implementation 

procedure TNewWebsite.InsertData(Data : TMyDataRecord); 

var 
    SQL : String; 

begin 
SQL := 'INSERT INTO website VALUES (:WID, :D1, :T, :Wh, :D2, :Od, :Rd, :Rc',+ 
     'Pm, :Ostat, :Cstat, :Rstat, :N, :U1, :P1, :P2, :Pstat, :CID)'; 
WebsiteTable.WebsiteQuery.ParamCheck := True; 
WebsiteTable.WebsiteQuery.SQL.Text := SQL; 
WebsiteTable.WebsiteQuery.Params.ParamByName('WID').AsString := Data.WID; 
WebsiteTable.WebsiteQuery.Params.ParamByName('D1').AsString := Data.D; 
...// rest of parameters 
WebsiteTable.WebsiteQuery.Params.ParamByName('CID').AsString := Data.CID; 
WebsiteTable.WebsiteQuery.ExecSQL; 
end; 
+0

wow большое спасибо. Я просто завершаю его, и я буду отмечать его, если он будет .EDIT: просто, чтобы вы знали, вы оставили + + в своем коде –

+0

Извините, я получаю сообщение об ошибке 'tsqlquery не содержит члена, называемого' Параметры '' –

+0

Я извиняюсь за ха-ха. Спасибо. Почти сделано сейчас –

1

Пожалуйста, замените '+CID+';)'); с '+CID+');'); в конце вашей линии запроса. ; был в неправильном месте.

0

, возможно, вы можете использовать его как этот

function FormatQuery(Query: String; Args: array of const): string; 
var S:string; FmtSet: TFormatSettings; 
begin 
    Result:= Query; 
    GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, FmtSet); 
    FmtSet.DecimalSeparator := '.'; 
    FmtStr(S, Query, Args, FmtSet); 
    Result:= S; 
end; 

procedure TNewWebsite.InsertData(Query: String; Args: array of const); 
var MyQuery: string; 
begin 
    MyQuery:= FormatQuery(Query, Args); 
    WebsiteTable.WebsiteQuery.SQL.Clear; 
    WebsiteTable.WebsiteQuery.SQL.Add(MyQuery); 
    WebsiteTable.WebsiteQuery.Open; 
end; 

После этого вы можете назвать это как этот

var MyQuery: string; 
MyQuery:= 'INSERT INTO website VALUES (%s,"%s","%s","%s","%s","%s","%s",%s,"%s",%s,%s,"%s","%s","%s","%s","%s",%s,%s;)'; 
InsertData(MyQuery,[WID,D,T,Wh,D,Od,Rd,Rc,Pm,Ostat,Cstat,Rstat,N,U1,P1,P2,Pstat,CID]); 

Я надеюсь, что может помочь и.

+2

этот код по-прежнему уязвим, как указано в моем ответе, downvoted – whosrdaddy

1

Недостаточно информации о таблице и данных, которые вы пытаетесь вставить, чтобы исправить свой код. Ответ T_G может быть правильным, и ответы, рекомендующие параметризованные запросы, хороши, но могут быть и другие ошибки. Я предложат вам несколько советов по диагностике вашей точной проблемы.

Во-первых, не пытайтесь отлаживать SQL-запросы через Delphi. Используйте инструмент администрирования базы данных, специально предназначенный для вашей базы данных, такой как MySQL Workbench http://www.mysql.com/products/workbench/. Это даст гораздо более подробные сообщения об ошибках, которые помогут вам найти причину ошибки.

Если вы создаете инструкцию SQL программно, как показано в вопросе, назначьте ее переменной, чтобы ее можно было захватить во время отладки, а затем скопировать ее в инструмент администратора базы данных по вашему выбору, чтобы отладить его.

var 
    SQL : string; 
begin 
    SQL := 'INSERT INTO website VALUES ('+WID+', '''+D+''', '''+T+''', '''+Wh+''', '''+D+''', '''+Od+''', '''+Rd+''', '+Rc+', '''+Pm+''', '+Ostat+', '+Cstat+', '''+Rstat+''', '''+N+''', '''+U1+''', '''+P1+''', '''+P2+''', '+Pstat+', '+CID+';)'); 
    WebsiteTable.WebsiteQuery.SQL.Text := SQL; 

Во-вторых, плохой практикой не включать имена столбцов в оператор SQL.Вы должны сделать свой SQL как следующий

INSERT INTO WEBSITE (COLUMN1, COLUMN2, COLUMN3) VALUES (1, 'ABC', 'XYZ') 

или с помощью параметризованных запросов

INSERT INTO WEBSITE (COLUMN1, COLUMN2, COLUMN3) VALUES (:C1, :C2, :C3) 

Да, это более типирование, но он предотвращает предположения от того причину ошибки, такие данные Зайдя в неправильные столбцы.

+3

Кроме того, если вы собираетесь вручную обернуть вставленные значения символами кавычек вместо использования параметризованного запроса, наименее использовать '(Ansi) QuotedStr()' для учета кавычек, находящихся внутри значений. Использование параметризованного запроса лучше всего избегать инъекций, но '(Ansi) QuotedStr()' является следующим лучшим вариантом при создании строк SQL. Простое перенос значений с окружающими кавычками, как показано, не является безопасным для инъекций, вам нужно избегать любых кавычек, которые содержатся внутри значений, например: 'SQL: = 'INSERT INTO website VALUES (' + WID + ',' + QuotedStr (D) + ',' + QuotedStr (T) + ',' + ...; ' –

+0

Привет. Я использую workbench, и мой sql работает отлично (без параметризации). Я получаю эту ошибку 'dbexpress driver не поддерживает tdbxtypes. Неизвестный тип данных. Что это значит? –

+2

Это должен быть еще один вопрос, потому что требуется больше информации. – crefird

Смежные вопросы