将表连接到函数时出现多部分标识符问题

时间:2014-07-29 09:51:00

标签: sql sql-server sql-server-2008 tsql

问题:

我的加入工作没有按预期进行:

join db1.function1(t1.id) f1 on f1.id = t1.id

错误消息是:

Incorrect syntax near '.'.
The multi-part identifier 't1.id' could not be found.

这个位(t1.id)带有红色波浪线下划线。

当我尝试使用cross apply时,我遇到了同样的问题。

该函数是一个表值函数,因此返回一个表。


完整查询示例:

select t1.*, f1.*
FROM db1.dbo.table1 t1
join db1.dbo.function1(t1.id) f1 on f1.id = t1.id

完整功能的简化版本

USE [DB1]

ALTER FUNCTION [dbo].[function1](@id int)
RETURNS @return_table TABLE (
    id INT, 
    col1 INT,
    col2 VARCHAR(255)
)
AS
BEGIN

    -- ...
    -- do all sorts of stuff here to get needed data, temp tables, unions, joins, inserts, selects etc
    -- ...

    INSERT INTO @return_table (id, col1, col2)
    select distinct id, col1,
    (
        select isnull(cast(col2 as varchar(3)),'NULL')+','
        from @tbl2 t2
        where t2.id = t1.id
        for xml path('')
    ) col2
    from @tbl1 a1

    RETURN;
END;

2 个答案:

答案 0 :(得分:1)

嗨所以基本上你想要表演INNER JOIN。你要解决的问题是你正在使用一个函数。您应该使用的是CROSS JOIN。如果需要保留加入,则可以使用OUTER JOIN

有一个伟大的艺术作品详细解释了过去对我的帮助,可以通过以下链接进行导航。 ClickMe。搜索Use case 5: APPLY and TVFs

我还编写了一些代码,可以为即时请求提供一些帮助

测试数据:

IF OBJECT_ID(N'Test1')>0
BEGIN
    DROP TABLE Test1
END
CREATE TABLE Test1 (Tbl1ID INT IDENTITY(1, 1),
                Name VARCHAR(250))

INSERT INTO Test1
VALUES('ABCD1'),
     ('ABCD2'),
     ('ABCD3'),
     ('ABCD4'),
     ('ABCD5'),
     ('ABCD6')

IF OBJECT_ID(N'Test2')>0
BEGIN
    DROP TABLE Test2
END
CREATE TABLE Test2 (Tbl2ID INT IDENTITY(1, 1),
                Name VARCHAR(250))

INSERT INTO Test2
VALUES('ABCD1'),
     ('ABCD2'),
     ('ABCD4'),
     ('ABCD5')

GO

电视功能

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ufn_TVFTable2]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[ufn_TVFTable2]
GO

CREATE FUNCTION ufn_TVFTable2 (@Name NVARCHAR(1000))
RETURNS TABLE
AS
RETURN
    SELECT *
    FROM Test2
    WHERE Name = @Name

GO

<强>用法:

SELECT t.*,tf.*
FROM Test1 AS T 
CROSS APPLY dbo.ufn_TVFTable2(T.name) AS tf 

<强>清理:

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ufn_TVFTable2]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[ufn_TVFTable2]
GO

IF OBJECT_ID(N'Test1')>0
BEGIN
    DROP TABLE Test1
END
IF OBJECT_ID(N'Test2')>0
BEGIN
    DROP TABLE Test2
END

您的查询如下所示:

SELECT t1.*,
       f1.*
FROM db1.dbo.table1 AS t1 
CROSS APPLY db1.dbo.function1(t1.id) AS f1

用法示例2:

;WITH cte_table1(ID) AS
(

SELECT 82938382 AS ID UNION ALL
SELECT 82938383 AS ID UNION ALL
SELECT 82938384 AS ID UNION ALL
SELECT 82938385 AS ID 

) 
SELECT t1.*,
       f1.*
FROM db1.dbo.table1 AS t1 
CROSS APPLY db1.dbo.function1(t1.id) AS f1

答案 1 :(得分:0)

您尝试在实际发生加入之前使用table1中的列加入函数。想一想function1作为原子操作的返回,然后你加入table1。那么在那时,SQL不知道id列的值是什么。

假设function1没有返回表格,您可能想要这样做:

SELECT t1.*, db1.dbo.function1(t1.id)
FROM db1.dbo.table1 t1