![为什么 SQL 查询不能用于子查询但可以用于逗号分隔列表?](https://linux22.com/image/752622/%E4%B8%BA%E4%BB%80%E4%B9%88%20SQL%20%E6%9F%A5%E8%AF%A2%E4%B8%8D%E8%83%BD%E7%94%A8%E4%BA%8E%E5%AD%90%E6%9F%A5%E8%AF%A2%E4%BD%86%E5%8F%AF%E4%BB%A5%E7%94%A8%E4%BA%8E%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E5%88%97%E8%A1%A8%EF%BC%9F.png)
我有疑问:
SELECT p.[id], p.[page_file], p.[page_header], p.[page_icon]
FROM [dbo].[setup_pages] AS p
WHERE CONVERT(nvarchar(100),p.[id]) IN ( SELECT l.[access] FROM [dbo].[licenses] AS l )
它没有返回错误,也没有返回任何数据。
SELECT l.[access] FROM [dbo].[licenses] AS l
返回 3 行:
1)8,9,15,4,13,11,5,14,12,16
2)20,19
3)20,8,9,15,4,13,11,5,14,12,16
如果我运行这样的查询:
SELECT p.[id], p.[page_file], p.[page_header], p.[page_icon]
FROM [dbo].[setup_pages] AS p
WHERE CONVERT(nvarchar(100),p.[id]) IN ( 8,9,15,4,13,11,5,14,12,16 )
它确实有效。...我的问题在哪里?
答案1
access
根据您的描述,表中的列似乎licenses
是一个包含字符串的字符列 - 其内容是以逗号分隔的数字列表。
因此,如果我们提取该结果SELECT l.[access] FROM [dbo].[licenses] AS l
并假装将其直接放入IN
,它看起来就不像您的第二个查询 - 相反,它看起来像这样:
SELECT p.[id], p.[page_file], p.[page_header], p.[page_icon]
FROM [dbo].[setup_pages] AS p
WHERE CONVERT(nvarchar(100),p.[id]) IN (
'8,9,15,4,13,11,5,14,12,16',
'20,19',
'20,8,9,15,4,13,11,5,14,12,16'
)
现在很清楚为什么第一个查询会失败 - 特定的id
fromsetup_pages
永远不会匹配 中的任何字符串licenses.access
。您可能需要查看数据库模型,并可能access
用“m:n”映射表替换该列。
顺便说一句:看起来您正在尝试使用CONVERT()
将id
字段转换为字符串,但这仍然不会使其与包含多个数字的字符串匹配,并且它也是不必要的 - 根据 SQL 标准,数据库服务器需要在简单的情况下自动执行此类转换,这就是为什么您的第二个查询实际上有效的原因,即使它将id
字符串形式的值与未格式化为字符串的数字列表进行比较。