我有这个功能:
CREATE FUNCTION [dbo].[full_ads](@date SMALLDATETIME)
returns TABLE
AS
RETURN
SELECT *,
COALESCE((SELECT TOP 1 ptype
FROM special_ads
WHERE [adid] = a.id
AND @date BETWEEN starts AND ends), 1) AS ptype,
(SELECT TOP 1 name
FROM cities
WHERE id = a.cid) AS city,
(SELECT TOP 1 name
FROM provinces
WHERE id = (SELECT pid
FROM cities
WHERE id = a.cid)) AS province,
(SELECT TOP 1 name
FROM models
WHERE id = a.mid) AS model,
(SELECT TOP 1 name
FROM car_names
WHERE id = (SELECT car_id
FROM models
WHERE id = a.mid)) AS brand,
(SELECT TOP 1 pid
FROM cities
WHERE id = a.cid) pid,
(SELECT TOP 1 car_id
FROM models
WHERE id = a.mid) bid,
(SELECT TOP 1 name
FROM colors
WHERE id = a.color_id) AS color,
COALESCE((SELECT TOP 1 fileid
FROM carimgs
WHERE adid = a.id), 'nocarimage.png') AS [image]
FROM ads a
WHERE isdeleted <> 1
有时它可以正常工作,但有时候列名不匹配(我已经用较少的列编写了一个示例结果来显示问题):
ID Name City Color Image
----------------------------------------------
1 John New York Null Red
2 Ted Chicago Null Blue
当您看到color
和Image
值被移动一列时,这将继续到最后一列。
谁能告诉我问题出在哪里?
答案 0 :(得分:9)
这是因为使用*
。
如果ads
的定义发生变化(添加或删除了列),则可能会破坏与TVF关联的元数据。
您需要在其上运行sp_refreshsqlmodule
以在此类更改后刷新此元数据。出于这个原因,最好避免在视图定义或内联TVF中使用*
。
这个例子
CREATE TABLE T
(
A CHAR(1) CONSTRAINT DF_A DEFAULT 'A',
B CHAR(1) CONSTRAINT DF_B DEFAULT 'B',
C CHAR(1) CONSTRAINT DF_C DEFAULT 'C',
D CHAR(1) CONSTRAINT DF_D DEFAULT 'D'
)
GO
INSERT INTO T DEFAULT VALUES
GO
CREATE FUNCTION F()
RETURNS TABLE
AS
RETURN
SELECT * FROM T
GO
SELECT * FROM F()
GO
ALTER TABLE T DROP CONSTRAINT DF_C, COLUMN C
ALTER TABLE T ADD E CHAR(1) DEFAULT 'E' WITH VALUES
GO
SELECT * FROM F()
返回
+---+---+---+---+
| A | B | C | D |
+---+---+---+---+
| A | B | D | E |
+---+---+---+---+
请注意,D
和E
值显示在错误的列中。它仍会显示列C
,即使它已被删除。