如何将派生列列表(表和列别名)应用于SQL Server

时间:2016-12-02 15:35:51

标签: sql sql-server tsql alias user-defined-functions

我在SQL Server中模拟PostgreSQL样式generate_series()表值函数:

CREATE FUNCTION generate_series(@d1 DATE, @d2 DATE)
RETURNS TABLE AS
RETURN
  -- Ignore implementation (returning a single DATE column) for this question

现在可以按预期使用:

SELECT *
FROM generate_series(
  CAST ('2005-07-01' AS DATE),
  CAST ('2005-07-31' AS DATE)
) t

现在,我想使用派生列列表语法将列重命名为表格,如下所示:

SELECT *
FROM generate_series(
  CAST ('2005-07-01' AS DATE),
  CAST ('2005-07-31' AS DATE)
) t(col)

产生此错误:

  

Msg 195,Level 15,State 15,Line 5
  ' generate_series'不是公认的功能名称。

...而这种语法(限定功能)......

SELECT *
FROM dbo.generate_series(
  CAST ('2005-07-01' AS DATE),
  CAST ('2005-07-31' AS DATE)
) t(col)

...正在产生此错误:

  

Msg 317,Level 16,State 1,Line 5
  表值函数" generate_series'不能有列别名。

在我看来,这种语法完全有效。它以这种方式在PostgreSQL,标准SQL和普通"中运行。也是T-SQL,例如:

SELECT *
FROM (
  VALUES (1),(2)
) t(col)

我做错了什么?我怎么能实现这个目标? (I'm aware of the possibility of emulating this,但我真的想使用派生列列表语法。)

我正在使用SQL Server Express 2014

3 个答案:

答案 0 :(得分:2)

SELECT *
FROM
    (
       SELECT *
       FROM dbo.generate_series(
        CAST ('2005-07-01' AS DATE),
        CAST ('2005-07-31' AS DATE)
    )) t(col)

我猜是因为虽然dbo.generate_series是一个函数,但它返回一个表。这样:

SELECT *
FROM
  TableName t(Col)

无效

但是

SELECT *
FROM
(
   SELECT *
   FROM
     TableName t
) t(col)

可行吗

所以换句话说,Derived Columns列表可以使用派生表,但不能在表派生时使用吗?

我认为我首选的语法是使用列别名而不是派生列列表。

SELECT d as Col
FROM
    dbo.generate_series(
        CAST ('2005-07-01' AS DATE),
        CAST ('2005-07-31' AS DATE)
    ) t

答案 1 :(得分:2)

在这种情况下,您无法添加列别名。这不是使用表值构造函数,而是从表值函数返回。只需删除列别名即可。

SELECT *
FROM dbo.generate_series(
  CAST ('2005-07-01' AS DATE),
  CAST ('2005-07-31' AS DATE)
) t

FWIW,我建议在你的函数中使用计数表而不是递归cte。如果您的日期范围很长,性能将受到影响,因为您实际上正在使用rcte进行计数。如果检查执行计划,它与while循环相同。杰夫莫登有一篇很棒的文章详细讨论了这个问题。 http://www.sqlservercentral.com/articles/T-SQL/74118/

- 编辑 -

要创建别名,您不能简单地添加别名吗?

SELECT t.d as MyAlias
FROM dbo.generate_series(
  CAST ('2005-07-01' AS DATE),
  CAST ('2005-07-31' AS DATE)
) t

答案 2 :(得分:1)

from子句的相关部分在这里。

column_alias仅支持派生表和@variable.function_call

[ FROM { <table_source> } [ ,...n ] ]   
<table_source> ::=   
{  
    table_or_view_name [ [ AS ] table_alias ]   
        [ <tablesample_clause> ]   
        [ WITH ( < table_hint > [ [ , ]...n ] ) ]   
    | rowset_function [ [ AS ] table_alias ]   
        [ ( bulk_column_alias [ ,...n ] ) ]   
    | user_defined_function [ [ AS ] table_alias ]  
    | OPENXML <openxml_clause>   
    | derived_table [ [ AS ] table_alias ] [ ( column_alias [ ,...n ] ) ]   
    | <joined_table>   
    | <pivoted_table>   
    | <unpivoted_table>  
    | @variable [ [ AS ] table_alias ]  
    | @variable.function_call ( expression [ ,...n ] )   
        [ [ AS ] table_alias ] [ (column_alias [ ,...n ] ) ]  
    | FOR SYSTEM_TIME <system_time>   
}  

所以,至少目前,你需要包装user_defined_function电话。例如在派生表或CTE中对列进行别名。