我想通过使用带参数的过程将记录插入数据库表(网站)。 SQL代码已经在mysql工作台中进行了测试,并且可以正常工作以插入新数据。但是,使用delphi,我在[插入整行代码]附近得到了一个“SQL语法”错误'。我想知道你们其中一个人是否可以告诉我哪里出错了。再次感谢。
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;
答案 0 :(得分:5)
您的代码中存在很多问题。
A)不要夸大函数参数,如果你有很多变量,可以根据需要将它们组装成记录或类。
B)您的SQL代码易受SQL注入攻击。您可能从未听说过SQL注入,请谷歌或阅读此really good answer。针对SQL注入的解决方案是使用参数(请参阅我的代码示例)。另外一个好处是,您的SQL语句将是人类可读的,并且不易出错。
C)Open
函数仅用于返回结果集的查询,例如SELECT
语句。对于INSERT
,DELETE
和UPDATE
语句,您需要使用ExecSQL
函数。
清理代码:
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;
答案 1 :(得分:1)
请在查询行末尾用'+CID+';)');
替换'+CID+');');
。 ;
位置错误。
答案 2 :(得分:1)
关于表格以及您尝试插入以修复代码的数据的信息不足。 T_G的答案可能是正确的,推荐参数化查询的答案很好但可能还有其他错误。我将就如何诊断您的确切问题向您提供一些建议。
首先,不要尝试通过Delphi调试SQL语句。使用专门为您的数据库设计的数据库管理工具,例如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语句中包含列名是不好的做法。您应该像以下
一样使用SQLINSERT INTO WEBSITE (COLUMN1, COLUMN2, COLUMN3) VALUES (1, 'ABC', 'XYZ')
或使用参数化查询
INSERT INTO WEBSITE (COLUMN1, COLUMN2, COLUMN3) VALUES (:C1, :C2, :C3)
是的,这是更多的输入,但它可以防止假设成为错误的原因,这些数据会进入错误的列。
答案 3 :(得分: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]);
我希望能帮到你。