带有联接+TClientDataSet空白字段的神秘参数化SQL查询

带有联接+TClientDataSet空白字段的神秘参数化SQL查询,sql,delphi,join,tclientdataset,Sql,Delphi,Join,Tclientdataset,有些时候,甚至是显而易见的事情似乎都出了问题。在处理SQL组件时,有很多明显的、肯定会出错的地方,当它们只是整个SQLQuery=>Provider=>ClientDataSet=>DataSource=>DataControl链的一环时,甚至会出错 今天的例子非常愚蠢,但却浪费时间 如何复制它: 删除一个TZQuery ZeosLib,在其SQL中使用一个简单的参数连接,例如: 选择 pr.product\U id作为product\U id, 公关模式作为模式, pd.name作为名称, 公

有些时候,甚至是显而易见的事情似乎都出了问题。在处理SQL组件时,有很多明显的、肯定会出错的地方,当它们只是整个SQLQuery=>Provider=>ClientDataSet=>DataSource=>DataControl链的一环时,甚至会出错

今天的例子非常愚蠢,但却浪费时间

如何复制它:

删除一个TZQuery ZeosLib,在其SQL中使用一个简单的参数连接,例如:

选择 pr.product\U id作为product\U id, 公关模式作为模式, pd.name作为名称, 公关形象作为形象, 公共地位作为地位, 请购单日期添加为日期添加, 请购单日期\u修改为日期\u修改 来自oc_产品公关部 左连接oc\u产品描述pd 在pr.product\u id=pd.product\u id和pd.language\u id=:language\u id上 哪里 pr.status=1 订购人 pd.name 当然我们有一个参数:language\u id

然后删除链接到它的TDataSetProvider,然后是TClientDataSet,然后是TDataSource,最后是TDBGrid,所有这些都链接到上一个。最后放下一个TDBNavigator并将其链接起来

最后,在TClientDataSet中添加字段、标题等

在程序启动时,我们将参数分配给TZQuery组件,如下所示:

qryProduct.Params.ParamByName'language_id'。AsInteger:=2; 其中2是实际应用程序中的演示硬编码值,它是通过查询正在使用的Windows当前语言确定的

现在运行应用程序:完美

现在按TDBNavigator上的刷新

要么您得到一个严重的:密钥冲突,要么在TDBGrid中得到一个完全空白的名称列


为什么?

解决方案是如此简单,但并不那么明显

通过TZSQLMonitor查看已联接表中生成的刷新SQL,很明显参数不起作用:

2014-01-04 11:19:38 cat: Execute, proto: mysql-5, msg: SELECT pr.product_id AS product_id,
pr.model AS model, pd.name AS name, pr.image AS image, pr.status AS status, pr.date_added
AS date_added, pr.date_modified AS date_modified FROM oc_product pr LEFT JOIN
oc_product_description pd ON pr.product_id = pd.product_id AND pd.language_id = NULL
WHERE pr.status = 1 ORDER BY pd.name
参数位为:

pd.language_id = NULL
快速浏览ClientDataSet组件将发现参数名已从查询组件中捕获。但不是价值

现在,我不知道TZQuery组件在运行时不发送参数值是不是有问题,或者该功能不是由ClientDataSet实现的,但它产生的错误远不是很明显


当然,修复方法是在Active设置为true之前,在TZQuery和TClientDataSet组件中手动设置参数值。

仅在ClientDataSet中设置参数就足够了。一个很好的地方是BeforeOpen事件。Delphi SQL设计的一个大问题是首先需要为每个参数执行整个费劲的param.parambyname.asinteger等操作。在单个函数调用中,应该只能够传递查询字符串和可变数量的值/变量。他们在新的REST库中犯了同样的错误。@uwerabe您有显示示例的链接吗?我找到了,但它似乎没有显示我所说的内容。@alcalde,该页面实际上显示了一个示例:FDConnection1.ExecSQL'insert-into-testtab-values:id,:name',[1,'FireDAC'];