SQL Server:表值函数的结果与列名不匹配

时间:2013-10-13 17:04:44

标签: sql-server stored-functions

我有这个功能:

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

当您看到colorImage值被移动一列时,这将继续到最后一列。

谁能告诉我问题出在哪里?

1 个答案:

答案 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 |
+---+---+---+---+

请注意,DE值显示在错误的列中。它仍会显示列C,即使它已被删除。