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

use*_*631 1 delphi ms-access ado delphi-7

我正在使用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) 
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

我一直试图找出它,但无论我使用什么代码,它都是同样的错误.错误是

项目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 ;
Run Code Online (Sandbox Code Playgroud)

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

Ken*_*ite 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;
Run Code Online (Sandbox Code Playgroud)

(正如你在问题的评论中所说的那样,错误无法移动.唯一可能导致问题的是ADOQuery1.ExecSQL;行,因为它是唯一执行该INSERT语句的行.任何其他行都不可能举起例外.)

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

首先,立即打破使用控件的默认名称的习惯,尤其是稍后需要从代码中访问的名称.您可以通过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);
Run Code Online (Sandbox Code Playgroud)

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

举个例子,如果用户决定把John';DROP TABLE Admins;edit14您的应用程序,并调用ExecSQL与SQL,你将不再有一个Admins表.如果改为使用它们会发生什么John';UPDATE Admins SET PASSWORD = NULL;?您现在没有任何管理员用户的密码.