在 T-SQL 查询的 SELECT 子句中使用表值函数的“语法不正确”

Posted

技术标签:

【中文标题】在 T-SQL 查询的 SELECT 子句中使用表值函数的“语法不正确”【英文标题】:"Incorrect syntax" using a table-valued function in SELECT clause of T-SQL query 【发布时间】:2011-02-24 10:53:19 【问题描述】:

我有以下用于拆分字符串的表值函数。这很好用,是从网络上的其他地方抄来的,我原以为不是问题的原因,但如果它是相关的,就会包括在内:

CREATE FUNCTION dbo.StringSplit (@sep char(1), @s varchar(512))
RETURNS table
AS
RETURN (
  WITH Pieces(pn, start, stop) AS (
    SELECT 1, 1, CHARINDEX(@sep, @s)
    UNION ALL
    SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
      FROM Pieces
    WHERE stop > 0
  )
  SELECT pn,
    SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
  FROM Pieces
)
GO

这会启用以下行:

SELECT * FROM dbo.StringSplit('.', 'this.is.a.string.to.split')

生产

PN | s ----+-------- 1 |这 2 |是 3 |一种 4 |细绳 5 |到 6 |分裂

我的目的是从包含大量文件名的表中获取文件扩展名列表。为此,我使用上面的表值函数来拆分每个文件名:

SELECT
  doc_id,
  doc_file_name,
  (SELECT TOP 1 s FROM dbo.StringSplit('.', doc_file_name) ORDER BY pn DESC) AS extension
FROM
  ai_docs_core

让 SQL Server 企业管理器检查其语法,在包含该函数的行上出现语法错误:

消息 102,第 15 级,状态 1,第 34 行 'doc_file_name' 附近的语法不正确。

以下内容不能满足我的需要(显然,因为它使用了一个集合变量),但它不会导致语法错误:

DECLARE @foo VARCHAR(512) = 'my_filename.doc'
SELECT
  doc_id,
  doc_file_name,
  (SELECT TOP 1 s FROM dbo.StringSplit('.', @foo) ORDER BY pn DESC) AS extension
FROM
  ai_docs_core

那么问题来了:为什么使用特定的字段名作为函数的参数会导致语法错误,我该如何实现我想要的呢?

【问题讨论】:

【参考方案1】:

我猜数据库设置为兼容模式 80 或更低。

见sp_dbcmptlevel

如果它发生在 FROM 子句中,这通常是原因

你也可以这样写

SELECT
  a.doc_id,
  a.doc_file_name,
  foo.extension 
FROM
  ai_docs_core a
  OUTER APPLY
  (SELECT TOP 1 s AS extension
   FROM dbo.StringSplit('.', a.doc_file_name)
   ORDER BY pn DESC
  ) foo

【讨论】:

正确答案。我查看了这个列表,看看是否可以看到与这种情况相关的兼容级别发生了什么变化,但我仍然不确定:msdn.microsoft.com/en-us/library/bb510680.aspx。对于看到此答案的其他人,另请注意 sp_dbcmptlevel 将被删除 - 现在建议使用 ALTER DATABASE [dbname] SET COMPATIBILITY_LEVEL = 80 | 90 | 100

以上是关于在 T-SQL 查询的 SELECT 子句中使用表值函数的“语法不正确”的主要内容,如果未能解决你的问题,请参考以下文章

在t-sql中,子查询只能放在where子句中吗

关于 Where 子句的 T-Sql 多重标准

在 T-SQL 中,如何在子查询中引用表变量?

T-SQL All-At-Once 操作解析

T-SQL查询2

使用T-SQL语句操作数据表-查询数据