在我的“产品编辑”页面上,我有一个选择列表,显示用户可以与产品关联的所有“文档”(从表中)。
<select name="pdid1" size="15" multiple id="pdid1" style="width:450px">
<cfoutput query="get">
<option value="#get.pdid#">
#pdname#
</option>
</cfoutput>
</select>
如果某个文档已与此产品相关联,我 希望它显示在<select>
列表中。
以下代码仅从“选择列表”中删除它在表中找到的第一个文档。因此,我需要遍历第一个查询,在第二个查询内部,以确保第一个查询从第二个查询中删除所有“匹配”。
<!---Checks for any docs already associated with this product--->
<cfquery name="find" datasource="#application.dsn#">
SELECT * FROM prodrelated
WHERE prprodid = '#url.id#'
</cfquery>
<!---Now remove any docs from the Select List query that are already associated with this product--->
<cfquery name="get" datasource="#application.dsn#">
SELECT * FROM productdocs
WHERE NOT productdocs.pdid = '#find.pritemid#'
</cfquery>
如何确保<select>
列表未显示任何已与此产品相关联的文档?
答案 0 :(得分:2)
而不是
WHERE NOT productdocs.pdid = '#find.pritemid#'
您想对原始查询中的所有行执行IN
WHERE productdocs.pdid NOT IN
(<cfqueryparam cfsqltype="cf_sql_integer" value="#valueList(find.pritemid)#" list="true">)
您应始终对所有动态数据库值使用cfqueryparam
valueList(find.pritemid)
创建一个逗号分隔的列表,其中包含“查找”查询中的所有pritemid值
list="true"
告诉cfqueryparam,它期待一个或多个列表。
答案 1 :(得分:1)
使用#find.pritemid#时,它只是查询返回的第一个pritemid。您可以将WHERE子句更改为:
WHERE productdocs.pdid NOT IN (#ValueList(find.pritemid)#)
这使用li
答案 2 :(得分:1)
除非您确实需要第一个查询中的数据用于其他内容,否则使用OUTER JOIN或甚至NOT EXISTS使用单个查询会更有效。这避免了额外查询的开销。尤其是检索比所需列更多的列,即select *
。此外,NOT IN (...)
子句的性能往往会降低列表中的值。
相反,使用OUTER JOIN仅返回匹配记录
SELECT pd.pdname, pd.pdid
FROM productdocs pd LEFT JOIN prodrelated pr
ON pd.pdid = pr.pritemid
AND pr.prprodid = <cfqueryparam value="#url.id#" cfsqltype="cf_sql_integer">
WHERE pr.prprodid IS NULL
NB:此外,只选择您需要的列,而不是SELECT *
。