我在insert into语句中有语法错误

时间:2013-09-04 22:09:23

标签: delphi ms-access delphi-7 ado

我正在使用MS Access数据库,Admins表中包含以下列:

Column        Type
======        ====
Name          Text 
Surname       Text 
Dateadded     Date/time 
Adminnumber   Number(long integer) 
Password      Text 
ID type       Autonumber  (Not sure if ID is relevant) 

这是我的代码,但它一直给我一个语法错误。

ADOquery1.Active := false;
adoquery1.sql.Text := 'insert into Admins(Name, surname, Adminnumber, Dateadded,password)Values('''+edit11.Text+''', '''+edit12.text+''', '''+edit13.Text+''', '''+edit14.Text+''', '''+edit15.text+''')';
ADOquery1.ExecSQL;
Adoquery1.SQL.Text := 'select * from Admins';
ADOquery1.Active := true;

我一直在努力寻找它,但无论我使用什么代码,它都会出现同样的错误。错误是

  

项目project1.exe引发了异常类eoleException       消息'INSERT INTO语句中的语法错误'。

我也尝试过:

ADOquery1.SQL.Add('Insert into admins');
ADOquery1.SQL.Add('(Name , Surname, Dateadded, Adminnumber, Password)');  
ADOquery1.SQL.Add('Values :Name, :Surname, :Dateadded, :adminnumber :Password)');
ADOquery1.Parameters.ParamByName('Name').Value := edit11.Text;
ADOquery1.Parameters.ParamByName('Surname').Value := edit12.Text;
ADOquery1.Parameters.ParamByName('Dateadded').Value := edit13.Text;
ADOquery1.Parameters.ParamByName('Password').Value := edit14.Text;
ADOquery1.Parameters.ParamByName('Adminnumber').Value := edit15.Text;
ADOquery1.ExecSQL;
ADOquery1.SQL.Text := 'Select * from admins';
ADOquery1.Open ;

但是这段代码给了我一个from子句

的问题

1 个答案:

答案 0 :(得分:9)

问题是Name(可能Password)是MS Access中的保留字。对于列名称来说,这是一个糟糕的选择,但是如果必须使用它,则应将其封闭在方括号([])中以将其转义。您在(语句后面还有一个左括号(VALUES),在:adminnumber参数后面还有一个逗号。

ADOquery1.SQL.Add('Insert into admins');
ADOquery1.SQL.Add('([Name] , [Surname], [Dateadded], [Adminnumber], [Password])');  
ADOquery1.SQL.Add('Values (:Name, :Surname, :Dateadded, :adminnumber, :Password)');
ADOquery1.Parameters.ParamByName('Name').Value := edit11.Text;
ADOquery1.Parameters.ParamByName('Surname').Value := edit12.Text;
ADOquery1.Parameters.ParamByName('Dateadded').Value := edit13.Text;
ADOquery1.Parameters.ParamByName('Password').Value := edit14.Text;
ADOquery1.Parameters.ParamByName('Adminnumber').Value := edit15.Text;
ADOquery1.ExecSQL;
ADOquery1.SQL.Text := 'Select * from admins';
ADOquery1.Open;

(正如您在问题的评论中所说,错误无法移动。唯一可能导致问题的行是ADOQuery1.ExecSQL;行,因为它是唯一执行INSERT行的行。 {1}}语句。任何其他行都不可能引发异常。)

您应该在此处进行一些更改,这些更改对代码的可维护性非常重要。

首先,立即打破使用控件默认名称的习惯,尤其是稍后需要从代码中访问的名称。您可以通过在Object Inspector中更改控件的Name属性来更改名称。

使用NameEdit.Text的代码比使用Edit1.Text要容易得多,尤其是当你到达Edit14时。如果Edit14被命名为PasswordEdit,那将会更加清晰,而且你会很高兴你从现在起六个月后必须更改代码。

其次,您应该避免在使用ParamByName().Value时使用字符串中的默认变体转换。当您分配到text列时,它可以正常工作,但当类型不是文本时(例如使用日期或数字时),它不是很好。在这些情况下,您应该在进行分配之前转换为正确的数据类型,以便确定它已正确完成。

ADOQuery1.ParamByName('DateAdded').Value := StrToDate(DateEdit.Text);
ADOQuery1.ParamByName('AdminNumber').Value := StrToInt(AdminNum.Text);

最后,你应该从不使用字符串连接,例如'SOME SQL'''+ Edit1.Text +''','''。这可能会导致严重的安全问题SQL injection,该问题可能允许恶意用户删除您的数据,删除表或重置用户ID和密码,并允许他们免费访问您的数据。 Google搜索会发现大量有关其可以创建的漏洞的信息。您甚至不应该在您认为安全的代码中执行此操作,因为将来可能会发生变化,或者您可能会遇到一个心怀不满的员工,他们决定在出路时遇到问题。

例如,如果用户决定将John';DROP TABLE Admins;放入您的应用中的edit14,并使用该SQL调用ExecSQL,则您将不再拥有Admins }表。如果他们改为使用John';UPDATE Admins SET PASSWORD = NULL;会发生什么?您现在没有任何管理员用户的密码。

相关问题