【问题标题】:Convert stored procedure to function将存储过程转换为函数
【发布时间】:2021-12-12 06:13:51
【问题描述】:

由于Direct Query数据连接模式,我需要使用一个函数才能通过Power BI使用它,Power BI无法使用存储过程。

因此我试图从存储过程中创建一个函数。

以下是我要从中创建函数的存储过程:

ALTER PROCEDURE [dbo].[SPTest]   
    @Anio int,
    @Mes int
AS
BEGIN
    DECLARE @AnioMes  varchar(8),
            @AnioMes6 varchar(8)

    IF @Anio IS NULL
        SELECT @Anio = YEAR(GETDATE()),
               @Mes  = MONTH(GETDATE())

    SELECT 
        @AnioMes = (CASE WHEN @Mes = 12 THEN @Anio + 1 ELSE @Anio END * 100 + 
                    CASE WHEN @Mes = 12 THEN 1 ELSE @Mes + 1 END) * 100 + 1
    SELECT
        @AnioMes6 = CONVERT(varchar(8), DATEADD(mm, -5, @AnioMes), 112)

    SELECT 
        YEAR(DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME)) * 100 + 
        MONTH(DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME)) AS AnioMes,
        DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME) AS FECHA_CREACION,
        INPUTSUBJECT,
        CASE 
            WHEN TOWTYPE = 1 THEN 'T1'
            WHEN TOWTYPE = 2 THEN 'T2'
            WHEN TOWTYPE = 3 THEN 'T3'
            WHEN TOWTYPE = 4 THEN 'T4'
            ELSE ''
        END AS TOWTYPE,
        [VENDNAME]
    FROM 
        TRUCKS
    WHERE
        YEAR(DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME)) >= yEAR(@AnioMes6)
        AND MONTH(DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME)) <= MONTH(@AnioMes)
        AND DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME) >= '20160701'

希望有人能给我一些关于如何从这个存储过程创建函数的指导

我已尝试执行以下操作:

CREATE FUNCTION [dbo].[SPTest]
(
    @Anio   int,
    @Mes    int,
    @AnioMes    varchar(8),
    @AnioMes6   varchar(8)
)
RETURNS TABLE
AS
BEGIN

        if @Anio is null
        Select  @Anio   = YEAR(GETDATE()),
                @Mes    = MONTH(GETDATE())

    Select  @AnioMes    = (case when @Mes=12 then @Anio+1 else @Anio end *100 + Case when @Mes=12 then 1 else @Mes+1 end)*100 + 1
    Select  @AnioMes6   = convert(varchar(8), DATEADD(mm, -5, @AnioMes), 112 )


    SELECT year(DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME))*100+month(DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME)) as AnioMes
          ,DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME) as FECHA_CREACION
          ,INPUTSUBJECT
          ,Case When TOWTYPE = 1 then 'T1'
                When TOWTYPE = 2 then 'T2'
                When TOWTYPE = 3 then 'T3'
                When TOWTYPE = 4 then 'T4'
                Else ''
            End as TOWTYPE
          ,[VENDNAME]
        FROM TRUCKS
        Where   year(DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME)) >= yEAR(@AnioMes6)
        and month(DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME)) <= MONTH(@AnioMes)
        AND     DATEADD(second, DATEDIFF(second, GETUTCDATE(), GETDATE()), CREATEDDATETIME) >= '20160701'

    END 

    RETURN

我在 BEGIN 中收到以下错误:

BEGIN 附近的语法不正确

【问题讨论】:

  • @DaleK 我已经根据文档尝试过,您可以查看我的最新更新
  • @DaleK 但是在我的情况下我不能忽略参数,我也在存储过程中使用它,我应该对函数进行任何更正吗?
  • 阅读CREATE FUNCTION (Transact-SQL) 文档。如果你想要一个像你现在这样的多语句表值函数,那么你需要指定你要返回的表的模式。
  • @DaleK 你的意思是这些变量@Anio @Month @YearMonth @ AnioMes6
  • @DaleK 由于 Direct Query 数据连接模式,我需要使用一个函数才能通过 Power BI 使用它,Power BI 无法使用存储过程,这就是为什么我不得不使用函数

标签: sql sql-server tsql stored-procedures


【解决方案1】:

首先,您应该始终尝试坚持内联表值函数,因为它们的性能要好得多。

内联函数没有BEGINEND,只能包含一个AS RETURN SELECT 语句。

  • 注意变量是如何转换成VALUES子句的
  • 避免对列使用函数。不要将CREATEDDATETIME 转换为时区进行比较,而是将您的参数转换为UTC
  • 出于同样的原因,不要比较日期的各个部分,构建起点和终点并与之进行比较
  • 不要使用字符串转换来创建日期,它很慢并且可能是不确定的。而是使用可用的适当日期函数
CREATE OR ALTER FUNCTION [dbo].[SPTest] (
    @month DATETIME
)
RETURNS TABLE
AS RETURN

SELECT
   v1.AnioMes
  ,t.CREATEDDATETIME AT TIME ZONE 'YourTimeZoneHere' as FECHA_CREACION
  ,t.INPUTSUBJECT
  ,CASE WHEN t.TOWTYPE IN (1,2,3,4)
        THEN CONCAT('T', t.TOWTYPE)
        ELSE '' END AS TOWTYPE
  ,t.[VENDNAME]

FROM (VALUES (
    DATEADD(day, 1, EOMONTH(TODATETIMEOFFSET(@month, 0)))
)) v1(AnioMes)

CROSS APPLY (VALUES (
    DATEADD(month, -5, v1.AnioMes)
)) v2(AnioMes6)

CROSS JOIN TRUCKS t

WHERE t.CREATEDDATETIME >= v2.AnioMes6
  AND t.CREATEDDATETIME <  v1.AnioMes
  AND t.CREATEDDATETIME >= '20160701';

【讨论】:

    猜你喜欢
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 2015-08-28
    • 2013-10-10
    • 2012-08-10
    • 2010-10-23
    • 2013-06-18
    相关资源
    最近更新 更多