SQL Server:在FUNCTION中使用大小写

时间:2012-08-08 13:21:29

标签: sql-server function case

SQL新手,经验丰富的VBA-er需要一些帮助。

我有一个关于需要获得特定类型的不同费用的交易的视图。费用在表中,其中一些字段是必需的,而其他字段可能是NULL。通过这种方式,我们可以设置一般的费用结构,并且仍然允许特定的特价。

我现在的目标是找到最合适的费用。这是费用:

  1. 符合所有必需条件,
  2. 匹配所有可选标准或对其有NULL
  3. 具有最匹配的所有费用的可选标准,通过1.和2.
  4. 现在我得到了这个代码的一个版本,但作为一个程序。但是因为我需要在视图中使用它,所以我不能使用该版本,并且函数中不允许使用临时表。

    在查看此论坛和其他人之后,我得出的结果仍然是2个错误:
      1. ErrorMessage:'@tblTEMP'附近的语法不正确,
      2. ErrorMessage:'BEGIN'附近的语法不正确。

    我当前的脚本如下(使用局部变量表):

    ALTER FUNCTION [dbo].[fnStandardFeeBAK]
      (@Type_Id BIGINT, @Party_Id BIGINT, @I_A_Id BIGINT, @Grid_Id BIGINT,
      @Market_Id BIGINT, @Counterparty_Id BIGINT, @Product_Id BIGINT, 
      @DealDate DATETIME)
    RETURNS TABLE
    
    AS
    
    BEGIN
      DECLARE @tblTEMP TABLE (Standard_Fee DECIMAL(38,8), Currency VARCHAR(50), 
      Unit VARCHAR(50), Unit2 VARCHAR(50), MatchScore BIGINT);
      WITH @tblTEMP AS 
      (SELECT Standard_Fee, V2.Element AS Currency, V1.Element AS Unit,
    V2.Element+'/'+V1.Element AS Unit2,
      SF.I_A_Id, SF.Grid_Id, SF.Product_Id, SF.Counterparty_Id,
      (CASE WHEN SF.I_A_Id = @I_A_Id THEN 1 ELSE 0 END +
          CASE WHEN SF.Grid_Id = @Grid_Id THEN 1 ELSE 0 END +
          CASE WHEN SF.Product_Id = @Product_Id THEN 1 ELSE 0 END +
          CASE WHEN SF.Counterparty_Id = @Counterparty_Id THEN 1 ELSE 0 END) 
          AS MatchScore
      FROM tblStandard_Fee AS SF
      LEFT JOIN tblElement AS V1 ON V1.Element_Id = SF.Unit_Id
      LEFT JOIN tblElement AS V2 ON V2.Element_Id = SF.Currency_Id
    
      WHERE SF.Type_Id = @Type_Id AND SF.Party_Id = @Party_Id AND 
        SF.Market_Id = @Market_Id
        AND SF.Date_From < @DealDate 
        AND (SF.Date_To > @DealDate OR SF.Date_To IS NULL)
        AND (SF.I_A_Id = @I_A_Id OR SF.I_A_Id IS NULL)
        AND (SF.Grid_Id = @Grid_Id OR SF.Grid_Id IS NULL)
        AND (SF.Product_Id = @Product_Id OR SF.Product_Id IS NULL)
        AND (SF.Counterparty_Id = @Counterparty_Id OR SF.Counterparty_Id IS NULL))
    RETURN
      SELECT Standard_Fee, Currency, Unit, Unit2
      FROM @tblTEMP
      WHERE MatchScore= MAX(MatchScore)
    END
    

    如果不让我知道,我希望我的问题很清楚。

    感谢您提出建议,甚至用最后一点解决我的问题!


    因此所有LittleBobbyTables的帮助结合起来给了我一个有效的结果。请不要忘记给他这个信用。

    工作代码:

    ALTER FUNCTION [dbo].[fnStandardFeeBAK]
    (@Type_Id BIGINT, @Party_Id BIGINT, @I_A_Id BIGINT, @Grid_Id BIGINT,
    @Market_Id BIGINT, @Counterparty_Id BIGINT, @Product_Id BIGINT, @DealDate DATETIME)
    
    RETURNS @YourTable TABLE 
    (
        -- Columns returned by the function
        Standard_Fee DECIMAL(38,8), 
        Currency VARCHAR(50), 
        Unit VARCHAR(50), 
        Unit2 VARCHAR(50)
    )
    AS
    
    BEGIN   
        WITH YourCTE(Standard_Fee, Currency, Unit, Unit2, MatchScore) AS
        (
        SELECT Standard_Fee, V2.Element AS Currency, V1.Element AS Unit,
            V2.Element + '/' + V1.Element AS Unit2,
            (CASE WHEN SF.I_A_Id = @I_A_Id THEN 1 ELSE 0 END +
            CASE WHEN SF.Grid_Id = @Grid_Id THEN 1 ELSE 0 END +
            CASE WHEN SF.Product_Id = @Product_Id THEN 1 ELSE 0 END +
            CASE WHEN SF.Counterparty_Id = @Counterparty_Id THEN 1 ELSE 0 END) 
            AS MatchScore
        FROM tblStandard_Fee AS SF
            LEFT JOIN tblElement AS V1 ON V1.Element_Id = SF.Unit_Id
            LEFT JOIN tblElement AS V2 ON V2.Element_Id = SF.Currency_Id
    
        --Type_ID, Party_ID and Market_Id are always present, others can have NULL values
        WHERE SF.Type_Id = @Type_Id AND SF.Party_Id = @Party_Id 
                AND SF.Market_Id = @Market_Id AND SF.Date_From < @DealDate 
                AND (SF.Date_To > @DealDate OR SF.Date_To IS NULL)
                AND (SF.I_A_Id = @I_A_Id OR SF.I_A_Id IS NULL)
                AND (SF.Grid_Id = @Grid_Id OR SF.Grid_Id IS NULL)
                AND (SF.Product_Id = @Product_Id OR SF.Product_Id IS NULL)
                AND (SF.Counterparty_Id = @Counterparty_Id OR SF.Counterparty_Id IS NULL)
        GROUP BY Standard_Fee, V1.Element, V2.Element, SF.I_A_Id, SF.Grid_Id, SF.Product_Id, SF.Counterparty_Id
        )
        INSERT @YourTable 
            SELECT Standard_Fee, Currency, Unit, Unit2
            FROM YourCTE 
            GROUP BY MatchScore, Standard_Fee, Currency, Unit, Unit2
            HAVING MatchScore = (SELECT MAX(MatchScore) FROM YourCTE)
    
         RETURN;
    END
    

1 个答案:

答案 0 :(得分:2)

请参阅Table-Valued User-Defined Functions文档,正确的语法是:

ALTER FUNCTION dbo.fnStandardFeeBAK(@Type_Id BIGINT, @Party_Id BIGINT, 
    @I_A_Id BIGINT, @Grid_Id BIGINT,  @Market_Id BIGINT, 
    @Counterparty_Id BIGINT, @Product_Id BIGINT, 
    @DealDate DATETIME)

RETURNS @YourTable TABLE 
(
    -- Columns returned by the function
    Standard_Fee DECIMAL(38,8), 
    Currency VARCHAR(50), 
    Unit VARCHAR(50), 
    Unit2 VARCHAR(50)
)
AS

最后:

    INSERT @YourTable 
    SELECT Standard_Fee, Currency, Unit, Unit2
    FROM YourCTE
    WHERE MatchScore= MAX(MatchScore)
    RETURN;
END;

编辑:搞砸了CTE,你不需要临时表。

把它们放在一起,你得到:

ALTER FUNCTION dbo.fnStandardFeeBAK(@Type_Id BIGINT, @Party_Id BIGINT, 
    @I_A_Id BIGINT, @Grid_Id BIGINT,  @Market_Id BIGINT, 
    @Counterparty_Id BIGINT, @Product_Id BIGINT, 
    @DealDate DATETIME)

RETURNS @YourTable TABLE 
(
    -- Columns returned by the function
    Standard_Fee DECIMAL(38,8), 
    Currency VARCHAR(50), 
    Unit VARCHAR(50), 
    Unit2 VARCHAR(50)
)
AS

BEGIN
 WITH YourCTE (Standard_Fee, Currency, Unit, Unit2, MatchScore) AS 
  (SELECT Standard_Fee, V2.Element AS Currency, V1.Element AS Unit,
V2.Element+'/'+V1.Element AS Unit2,
  SF.I_A_Id, SF.Grid_Id, SF.Product_Id, SF.Counterparty_Id,
  (CASE WHEN SF.I_A_Id = @I_A_Id THEN 1 ELSE 0 END +
      CASE WHEN SF.Grid_Id = @Grid_Id THEN 1 ELSE 0 END +
      CASE WHEN SF.Product_Id = @Product_Id THEN 1 ELSE 0 END +
      CASE WHEN SF.Counterparty_Id = @Counterparty_Id THEN 1 ELSE 0 END) 
      AS MatchScore
  FROM tblStandard_Fee AS SF
  LEFT JOIN tblElement AS V1 ON V1.Element_Id = SF.Unit_Id
  LEFT JOIN tblElement AS V2 ON V2.Element_Id = SF.Currency_Id

  WHERE SF.Type_Id = @Type_Id AND SF.Party_Id = @Party_Id AND 
    SF.Market_Id = @Market_Id
    AND SF.Date_From < @DealDate 
    AND (SF.Date_To > @DealDate OR SF.Date_To IS NULL)
    AND (SF.I_A_Id = @I_A_Id OR SF.I_A_Id IS NULL)
    AND (SF.Grid_Id = @Grid_Id OR SF.Grid_Id IS NULL)
    AND (SF.Product_Id = @Product_Id OR SF.Product_Id IS NULL)
    AND (SF.Counterparty_Id = @Counterparty_Id OR SF.Counterparty_Id IS NULL))

  INSERT @YourTable 
    SELECT Standard_Fee, Currency, Unit, Unit2
    FROM YourCTE
    WHERE MatchScore= MAX(MatchScore)
  RETURN;
END;