【问题标题】:SQL Server Incorrect syntax near '(' in recursive querySQL Server递归查询中“(”附近的语法不正确
【发布时间】:2017-04-12 14:52:05
【问题描述】:

我正在尝试将 IBM db2 查询转换为 SQL Server 查询。我对 WITH AS 构造不是很熟悉。

db2 查询(有效)是:

with ZoneList (id, name, parent_name, parent_id, level) as 
(select id, name, '', parent_id, 1 as level 
from products.zones where id = 1 
union all 
select z.id, z.name, l.name, z.parent_id, level + 1 
from products.zones z, ZoneList l
where z.parent_id = l.id) 
select id, name || ' (' || parent_name || ')' as description 
from ZoneList
where level = 4 
order by ZoneList.name

而我的 SQL Server 版本是:

with ZoneList (id, name, cast((parent_name) as varchar(45)), parent_id, 
level) as 
(select id, name, cast(('') as varchar(45)), parent_id, 1 as level 
from products.zones where id = 1 
union all 
select z.id, z.name, cast((l.name) as varchar(45)), z.parent_id, level + 1 
from products.zones z, ZoneList l 
where z.parent_id = l.id) 
select id, name + ' (' + parent_name + ')' as description 
from ZoneList 
where level = 4 
order by ZoneList.name

为了避免不兼容类型错误,我添加了强制转换,但现在我在 '(' 附近出现语法错误。

【问题讨论】:

  • 而不是第一行的cast((parent_name) as varchar(45)),只需使用parent_name--with ZoneList (id, name, parent_name, parent_id, level) as 。你说的是列名是什么,所以你不需要类型声明或强制转换。

标签: sql sql-server common-table-expression recursive-query


【解决方案1】:

试试这个:

;with ZoneList (id, name, parent_name, parent_id, level)
as (
    select id
        , name
        , cast('' as varchar(45))
        , parent_id
        , 1 as level
    from products.zones
    where id = 1

    union all

    select z.id
        , z.name
        , cast(l.name as varchar(45))
        , z.parent_id
        , level + 1
    from products.zones z
        inner join ZoneList l 
            on z.parent_id = l.id
    )
select id
    , name + ' (' + parent_name + ')' as description
from ZoneList
where level = 4
order by ZoneList.name

您不需要在第一行中进行任何显式强制转换,因为在第一行中您枚举了 CTE 的列,您没有定义它们的数据类型或大小等。

您甚至可以完全删除 CTE 顶部的列枚举,只要您为 CTE 中的每一列设置别名,例如:

;with ZoneList
as (
    select id
        , name
        , cast('' as varchar(45)) as [parent_name]
        , parent_id
        , 1 as level
    from products.zones
    where id = 1

    union all

    select z.id
        , z.name
        , cast(l.name as varchar(45))  as [parent_name]
        , z.parent_id
        , level + 1
    from products.zones z
        inner join ZoneList l 
            on z.parent_id = l.id
    )
select id
    , name + ' (' + parent_name + ')' as description
from ZoneList
where level = 4
order by ZoneList.name

【讨论】:

  • 我还建议将隐式连接更改为显式连接。
  • @ZoharPeled 改进
【解决方案2】:

common table expression 的列列表不是您要转换该值的位置。

with ZoneList  (id, name, parent_name, parent_id, level) as (
select 
    id
  , name
  , cast(('') as varchar(45)) as parent_name
  , parent_id
  , 1 as level 
from products.zones where id = 1 

union all 

select 
    z.id
  , z.name
  , cast((l.name) as varchar(45)) as parent_name
  , z.parent_id
  , level + 1 
from products.zones z
  inner join ZoneList l 
    on z.parent_id = l.id
) 
select 
    id
  , name + ' (' + parent_name + ')' as description 
from ZoneList 
where level = 4 
order by ZoneList.name

【讨论】:

  • 我还建议将隐式连接更改为显式连接。
  • @ZoharPeled 好渔获
猜你喜欢
  • 1970-01-01
  • 2014-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-26
  • 2014-02-09
相关资源
最近更新 更多