【问题标题】:SQL EXEC PROCEDURE: "Must declare the scalar variable "@p1"SQL EXEC PROCEDURE:“必须声明标量变量“@p1”
【发布时间】:2020-04-08 21:22:57
【问题描述】:

当我尝试执行下面的存储过程时出现以下错误:

Must declare the scalar variable "@p1"

我不明白为什么或如何解决,任何帮助将不胜感激。谢谢

存储过程:

USE [SERVER_NAME]
GO
/****** Object:  StoredProcedure [dbo].[APP_jdtest_shp_0]    Script Date: 16/12/2019 11:13:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[jdtest_shp_0] 
    @p1 nvarchar(100),  
    @n nvarchar(100) 
AS 
EXEC('
    CREATE VIEW dbo.[' + @n + '] AS 
    SELECT 
        RTRIM([F].[F_CODE]) As F_UID ,  
        RTRIM([TP].[F_TP_NAME]) As F_TP_UID ,  
        RTRIM([NS].[F_CODE]) AS F_CODE,  
        RTRIM([NS].[SOME_DATE]) AS SOME_DATE,  
        RTRIM([NS].[ANOTHER_DATE]) AS ANOTHER_DATE,  
        RTRIM([NS].[SPD]) AS SPD,  
        RTRIM([NS].[LK_DATE]) AS LK_DATE,  
        RTRIM([NS].[RC_DATE]) AS RC_DATE,  
        RTRIM([NS].[RD_DATE]) AS RD_DATE,  
        RTRIM([NS].[OLD_UID]) AS OLD_UID,  
        RTRIM([NS].[VN]) AS VN,  
        RTRIM([NS].[R_I]) AS R_I,  
        RTRIM([NS].[WTU_UID]) AS WTU_UID,  
        RTRIM([NS].[D_LT]) AS D_LT,  
        RTRIM([PLT_UD].[PLT]) As L_A_PLT_UD_UID ,  
        RTRIM([RT].[RT_NAME]) As RT_UID ,  
        RTRIM([SS].[S_S_NAME]) As S_S_UID ,  
        RTRIM([NS].[S_DATE]) AS S_DATE,  
        RTRIM([SUR].[S_SUR_NAME]) As S_SUR_UID ,  
        RTRIM([NS].[S_TOL]) AS S_TOL,  
        RTRIM([LKP_AUTH].[AUTH_NAME]) As AUTH_UID ,  
        [NS].[S_G] AS S_G,  
        RTRIM([NS].[NS_UID]) AS NS_UID,  
        RTRIM([NSG_C].[C_NAME]) As C_UID ,  
        RTRIM([NS].[CLT]) AS CLT,  
        RTRIM([NS].[ONR_UID]) AS ONR_UID,  
        RTRIM([NC].[S_CLF_NAME]) As S_CLF_UID , 
        RTRIM([NS].[XP]) AS XP,  
        RTRIM([NS].[CSTART_X]) AS CSTART_X,  
        RTRIM([NS].[CSTART_Y]) AS CSTART_Y,  
        RTRIM([NS].[CEND_X]) AS CEND_X,  
        RTRIM([NS].[CEND_Y]) AS CEND_Y 
    FROM NS  
    LEFT OUTER JOIN F ON NS.F_UID = F.F_UID 
    LEFT OUTER JOIN FT ON NS.F_TP_UID = FT.FT_UID 
    LEFT OUTER JOIN PLT_UD ON NS.L_A_PLT_UD_UID = SEC_PLT_UD.PLT_UD_UID 
    LEFT OUTER JOIN RT ON NS.RT_UID = RT.RT_UID 
    LEFT OUTER JOIN STT ON NS.S_S_UID = SS.S_S_UID 
    LEFT OUTER JOIN SUR ON NS.S_SUR_UID = SUR.S_SUR_UID 
    LEFT OUTER JOIN AUTH ON NS.AUTH_UID = AUTH.AUTH_UID 
    LEFT OUTER JOIN C ON NS.C_UID = C.C_UID 
    LEFT OUTER JOIN NSC ON NS.S_CLF_UID = NSC.S_CLF_UID 
WHERE  
    ([NS].[SHAPE_GEOMETRY].STIntersects(Geometry::STGeomFromText(' + '@p1' + ', 0).MakeValid())>0) AND  
    ([NS].[S_G].STGeometryTP() = ''POINT'')  '
)

编辑:使用 sql server 2014。这不是我的代码,我正在尝试修复其他人代码中的错误。

更新:更新了“执行命令”部分以显示过程是如何执行的

【问题讨论】:

  • 在动态 SQL 中使用格式以提高可读性与格式化非动态 SQL 一样同样重要
  • 您的答案向您展示了正确的做事方式。但是,如果您只是选择生成的字符串作为用于调试目的的输出,那么您的代码问题就会很明显。然后您会注意到您只是在查询中嵌入了参数的名称 - 当您打算嵌入字符串中包含的值时。如果你想写动态sql,你必须能看到生成的代码来调试它。
  • 您需要一个存储过程来创建一个非常、非常特定的视图,这有点奇怪。更重要的是,现在完全不支持sql server 2008;应该有人对此感到担忧。
  • 抱歉,我忘了我们几周前更新到 sql server 2014。这也不是我的代码,而是别人的,我只是想修复这个错误。
  • 我不明白为什么你需要像这样一遍又一遍地生成视图。为什么不接收@p1 的过程或视图并在从中选择时使用 where 子句?生成一个又一个视图,只对 where 谓词稍作更改就表明存在设计问题。

标签: sql asp.net sql-server vb.net sql-server-2014


【解决方案1】:

如果要在动态语句中使用参数,则需要使用sp_executesql 而不是EXEC()

CREATE PROCEDURE [dbo].[123456] 
    @p1 nvarchar(100),  
    @n nvarchar(100) 
AS 
BEGIN
    DECLARE @stm nvarchar(max)
    DECLARE @err int

    SET @stm = 
        N'CREATE VIEW dbo.' + QUOTENAME(@n) + N' AS ' +
        N'SELECT 
            RTRIM([FEATURE].[FEATURE_CODE]) As FEATURE_UID ,  
            RTRIM([FEATURE_TYPE].[FEATURE_TYPE_NAME]) As FEATURE_TYPE_UID ,  
            RTRIM([NSG_STREETS].[FEATURE_CODE]) AS FEATURE_CODE,  
            RTRIM([NSG_STREETS].[START_DATE]) AS START_DATE,  
            RTRIM([NSG_STREETS].[END_DATE]) AS END_DATE,  
            RTRIM([NSG_STREETS].[SUSPEND_ACTIVITIES]) AS SUSPEND_ACTIVITIES,  
            RTRIM([NSG_STREETS].[RECORD_ENTRY_DATE]) AS RECORD_ENTRY_DATE,  
            RTRIM([NSG_STREETS].[RECORD_CHANGE_DATE]) AS RECORD_CHANGE_DATE,  
            RTRIM([NSG_STREETS].[RECORD_DELETE_DATE]) AS RECORD_DELETE_DATE,  
            RTRIM([NSG_STREETS].[OLD_SYSTEM_UID]) AS OLD_SYSTEM_UID,  
            RTRIM([NSG_STREETS].[VERSION_NUMBER]) AS VERSION_NUMBER,  
            RTRIM([NSG_STREETS].[RECORD_IDENTIFIER]) AS RECORD_IDENTIFIER,  
            RTRIM([NSG_STREETS].[WARD_UID]) AS WARD_UID,  
            RTRIM([NSG_STREETS].[DIGITAL_LENGTH]) AS DIGITAL_LENGTH,  
            RTRIM([SEC_USER].[USER_NAME]) As LAST_EDIT_USER_UID ,  
            RTRIM([LKP_RECORD_TYPE].[RECORD_TYPE_NAME]) As RECORD_TYPE_UID ,  
            RTRIM([LKP_STREET_STATE].[STREET_STATE_NAME]) As STREET_STATE_UID ,  
            RTRIM([NSG_STREETS].[STATE_DATE]) AS STATE_DATE,  
            RTRIM([LKP_STREET_SURFACE].[STREET_SURFACE_NAME]) As STREET_SURFACE_UID ,  
            RTRIM([NSG_STREETS].[STREET_TOLERANCE]) AS STREET_TOLERANCE,  
            RTRIM([LKP_AUTHORITY].[AUTHORITY_NAME]) As AUTHORITY_UID ,  
            [NSG_STREETS].[SHAPE_GEOGRAPHY] AS SHAPE_GEOGRAPHY,  
            RTRIM([NSG_STREETS].[NSG_STREETS_UID]) AS NSG_STREETS_UID,  
            RTRIM([NSG_COUNTY].[COUNTY_NAME]) As COUNTY_UID ,  
            RTRIM([NSG_STREETS].[CLASS_UID]) AS CLASS_UID,  
            RTRIM([NSG_STREETS].[OWNER_UID]) AS OWNER_UID,  
            RTRIM([NSG_STREET_CLASSIFICATION].[STREET_CLASSIFICATION_NAME]) As STREET_CLASSIFICATION_UID ,  
            RTRIM([NSG_STREETS].[EXPORT]) AS EXPORT,  
            RTRIM([NSG_STREETS].[CSTART_X]) AS CSTART_X,  
            RTRIM([NSG_STREETS].[CSTART_Y]) AS CSTART_Y,  
            RTRIM([NSG_STREETS].[CEND_X]) AS CEND_X,  
            RTRIM([NSG_STREETS].[CEND_Y]) AS CEND_Y FROM NSG_STREETS  
        LEFT OUTER JOIN FEATURE ON NSG_STREETS.FEATURE_UID = FEATURE.FEATURE_UID 
        LEFT OUTER JOIN FEATURE_TYPE ON NSG_STREETS.FEATURE_TYPE_UID = FEATURE_TYPE.FEATURE_TYPE_UID 
        LEFT OUTER JOIN SEC_USER ON NSG_STREETS.LAST_EDIT_USER_UID = SEC_USER.USER_UID 
        LEFT OUTER JOIN LKP_RECORD_TYPE ON NSG_STREETS.RECORD_TYPE_UID = LKP_RECORD_TYPE.RECORD_TYPE_UID 
        LEFT OUTER JOIN LKP_STREET_STATE ON NSG_STREETS.STREET_STATE_UID = LKP_STREET_STATE.STREET_STATE_UID 
        LEFT OUTER JOIN LKP_STREET_SURFACE ON NSG_STREETS.STREET_SURFACE_UID = LKP_STREET_SURFACE.STREET_SURFACE_UID 
        LEFT OUTER JOIN LKP_AUTHORITY ON NSG_STREETS.AUTHORITY_UID = LKP_AUTHORITY.AUTHORITY_UID 
        LEFT OUTER JOIN NSG_COUNTY ON NSG_STREETS.COUNTY_UID = NSG_COUNTY.COUNTY_UID 
        LEFT OUTER JOIN NSG_STREET_CLASSIFICATION ON NSG_STREETS.STREET_CLASSIFICATION_UID = NSG_STREET_CLASSIFICATION.STREET_CLASSIFICATION_UID 
        WHERE  
            ([NSG_STREETS].[SHAPE_GEOMETRY].STIntersects(Geometry::STGeomFromText(@p1, 0).MakeValid())>0) AND  
            ([NSG_STREETS].[SHAPE_GEOGRAPHY].STGeometryType() = ''POINT'')  '

    EXEC @err = sp_executesql @stm, N'@p1 nvarchar(100)', @p1

    IF @err <> 0 BEGIN
        PRINT 'Error'
        RETURN @err
    END
END

【讨论】:

  • 'dbo.[' + @n + '] AS ' 应该是 N'dbo.' + QUOTENAME(@n) + N' AS '。否则这只是一个等待被利用的注入问题。
  • 谢谢@Larnu,注入问题总是很重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
相关资源
最近更新 更多