如何使用FireDAC DBMS标识符实现SQL文本的条件切换
问题解决说明
你遇到的语法报错核心原因是FireDAC的SQL条件预处理器默认未启用,你写的{IF MSSQL}、{IF PG}这类条件指令没有被解析过滤,所有内容都作为普通SQL文本直接发送给了PostgreSQL服务端,PG无法识别MSSQL相关的语法片段,因此抛出如下错误:
[FireDAC][Phys][PG][libpq] ERROR: syntax error at or near "select"
修复配置
你只需要补充1项配置即可启用预处理器:
- 给
TFDConnection或者TFDQuery的ResourceOptions.PreprocessCmdText属性设为True,该属性默认值为False,是预处理器不生效的核心原因。
修正后完整代码
procedure TForm1.Button2Click(Sender: TObject); var Conn: TFDConnection; Qry: TFDQuery; IdParam: TFDParam; begin Conn := TFDConnection.Create(nil); try Conn.ConnectionString := 'DriverID=PG;Server=localhost;Database=postgres;User_Name=user;Password=pass;'; // 启用连接级别的SQL预处理,所有关联的查询都会自动生效 Conn.ResourceOptions.PreprocessCmdText := True; Conn.Connected := True; Qry := TFDQuery.Create(nil); try Qry.Connection := Conn; Qry.SQL.Text := 'INSERT INTO people (name) VALUES (:name) ' + '{IF MSSQL} select :id = @@identity {FI}' + '{IF PG} returning id {INTO :id} {FI}'; Qry.ParamByName('name').AsString := 'George Smith'; IdParam := Qry.ParamByName('id'); IdParam.ParamType := ptOutput; IdParam.DataType := ftInteger; Qry.Prepare; Qry.ExecSQL; ShowMessage(IntToStr(IdParam.AsInteger)); finally Qry.Free; end; finally Conn.Free; end; end;
生效逻辑说明
配置开启后,FireDAC会自动根据当前连接的DriverID过滤SQL语句:
- 连接PG数据库时,最终发送给服务端的SQL为
INSERT INTO people (name) VALUES (:name) returning id,MSSQL相关的语句片段会被完全移除 - 连接MSSQL数据库时,最终发送给服务端的SQL为
INSERT INTO people (name) VALUES (:name) select :id = @@identity,PG相关的语句片段会被完全移除
语法错误会直接消失,输出参数也可以正常获取自增ID值。
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

