如何在SQL Server函数中指定列名?

如何在SQL Server函数中指定列名?,sql,sql-server,Sql,Sql Server,问题是,我有几个特定购买订单的寄存器,因为每个寄存器都是同一次购买中不同产品的寄存器,首先我执行了以下功能: CREATE FUNCTION TOTALORDEN (@id_orden INT) RETURNS float AS BEGIN DECLARE @total FLOAT SELECT @total = UnitPrice * Quantity - UnitPrice * Quantity * Discount FROM [Order Details]

问题是,我有几个特定购买订单的寄存器,因为每个寄存器都是同一次购买中不同产品的寄存器,首先我执行了以下功能:

CREATE FUNCTION TOTALORDEN (@id_orden INT)
RETURNS float
AS
BEGIN
    DECLARE @total FLOAT

    SELECT @total = UnitPrice * Quantity - UnitPrice * Quantity * Discount 
    FROM [Order Details] 
    WHERE @id_orden = OrderID

    RETURN @total
END
但该函数的问题是只打印最后一个寄存器的结果

然后我决定在select指令上使用SQL算法,函数如下:

CREATE FUNCTION TOTALORDEN (@id_orden INT)
RETURNS table

    RETURN (SELECT (UnitPrice * Quantity) -
                   (UnitPrice * Quantity * Discount) 
            FROM [Order Details] 
            WHERE @id_orden = OrderID)
它显示的错误是:

Msg 4514,16级,状态1,程序总计,第3行
CREATE函数产生错误,因为没有为列1指定列名

表中的部分数据:


我猜您错过了聚合函数
SUM()


我猜您错过了聚合函数
SUM()


如果不告诉SQL返回的列的名称,SQL就不喜欢它。我使用了FinalPrice的列名,您可以将其更改为您想要的名称。此外,如果您计划使用此函数更新表等,则在表中返回orderid会很有帮助。这应该起作用:

CREATE FUNCTION [TOTALORDEN] ( @id_orden INT )
RETURNS TABLE
RETURN
(
SELECT OrderId, SUM(( [UnitPrice] * [Quantity] ) - ( [UnitPrice] * [Quantity] * [Discount]) ) AS FinalPrice
FROM
    [Order Details]
WHERE [OrderID] = @id_orden
Group BY OrderId
)
此外,如果您只需要返回总的订单和,那么使用表值函数是一种过度使用。你应该使用

CREATE FUNCTION [TOTALORDEN] ( @id_orden INT )
RETURNS FLOAT
AS
BEGIN
DECLARE @total FLOAT

SELECT
    @total = SUM (([UnitPrice] * [Quantity]) - ([UnitPrice] * [Quantity] * [Discount]))
FROM
    [Order Details]
WHERE [OrderID] = @id_orden 

RETURN @total
END

也不建议在表名中使用空格,如果您不告诉SQL返回的列的名称,您也应该考虑重构。我使用了FinalPrice的列名,您可以将其更改为您想要的名称。此外,如果您计划使用此函数更新表等,则在表中返回orderid会很有帮助。这应该起作用:

CREATE FUNCTION [TOTALORDEN] ( @id_orden INT )
RETURNS TABLE
RETURN
(
SELECT OrderId, SUM(( [UnitPrice] * [Quantity] ) - ( [UnitPrice] * [Quantity] * [Discount]) ) AS FinalPrice
FROM
    [Order Details]
WHERE [OrderID] = @id_orden
Group BY OrderId
)
此外,如果您只需要返回总的订单和,那么使用表值函数是一种过度使用。你应该使用

CREATE FUNCTION [TOTALORDEN] ( @id_orden INT )
RETURNS FLOAT
AS
BEGIN
DECLARE @total FLOAT

SELECT
    @total = SUM (([UnitPrice] * [Quantity]) - ([UnitPrice] * [Quantity] * [Discount]))
FROM
    [Order Details]
WHERE [OrderID] = @id_orden 

RETURN @total
END

也不建议在表名中使用空格,您应该考虑重构,因为SQL Server标量函数在SQL Server中的性能不好,您应该尽量避免使用空格。内联表值函数更好,但在这种情况下,我更喜欢以下视图:

CREATE VIEW OrderDetailsSummary
WITH SCHEMABINDING
AS
    SELECT od.OrderID, SUM (ISNULL(od.Quantity * od.UnitPrice * (1 - CAST(od.Discount AS money)), 0)) as OrderTotal, COUNT_BIG(*) AS OrderLineCount
    FROM 
        dbo.OrderDetails od
    GROUP BY
        od.OrderID

GO
此视图可以编制索引,使其迅雷不及掩耳:

CREATE UNIQUE CLUSTERED INDEX UX_OrderDetailsSummary
ON OrderDetailsSummary(OrderID)
现在,您可以通过以下简单查询获得订单总额和订单行数:

SELECT *
FROM OrderDetailsSummary WITH (NOEXPAND)
WHERE OrderID = 10260
这是非常有效的。我只需要2个逻辑读取:

(1行受影响)表“OrderDetailsSummary”。扫描计数0,逻辑 读取2,物理读取0,预读读取0,lob逻辑读取0, lob物理读取0,lob预读读取0

这是执行计划:

此外,该视图还可以与其他视图和表连接。例如,您可以获得订单信息和摘要数据:

SELECT O.OrderID, O.CustomerID, O.OrderDate, S.OrderTotal, S.OrderLineCount
FROM
    dbo.Orders O
    LEFT OUTER JOIN dbo.OrderDetailsSummary S WITH (NOEXPAND)
        ON O.OrderID = S.OrderID

SQL Server标量函数在SQL Server中的性能不好,您应该尽量避免使用它们。内联表值函数更好,但在这种情况下,我更喜欢以下视图:

CREATE VIEW OrderDetailsSummary
WITH SCHEMABINDING
AS
    SELECT od.OrderID, SUM (ISNULL(od.Quantity * od.UnitPrice * (1 - CAST(od.Discount AS money)), 0)) as OrderTotal, COUNT_BIG(*) AS OrderLineCount
    FROM 
        dbo.OrderDetails od
    GROUP BY
        od.OrderID

GO
此视图可以编制索引,使其迅雷不及掩耳:

CREATE UNIQUE CLUSTERED INDEX UX_OrderDetailsSummary
ON OrderDetailsSummary(OrderID)
现在,您可以通过以下简单查询获得订单总额和订单行数:

SELECT *
FROM OrderDetailsSummary WITH (NOEXPAND)
WHERE OrderID = 10260
这是非常有效的。我只需要2个逻辑读取:

(1行受影响)表“OrderDetailsSummary”。扫描计数0,逻辑 读取2,物理读取0,预读读取0,lob逻辑读取0, lob物理读取0,lob预读读取0

这是执行计划:

此外,该视图还可以与其他视图和表连接。例如,您可以获得订单信息和摘要数据:

SELECT O.OrderID, O.CustomerID, O.OrderDate, S.OrderTotal, S.OrderLineCount
FROM
    dbo.Orders O
    LEFT OUTER JOIN dbo.OrderDetailsSummary S WITH (NOEXPAND)
        ON O.OrderID = S.OrderID