Member 14476420 Ответов: 4

Процедура Sql EXEC: “необходимо объявить скалярную переменную ”@p1"


I am trying to fix a bug in someone else's code. The executeNonReader() command below produces the following error:

Must declare the scalar variable "@p1"

I don't understand why or how to fix as both parameters are being passed and having looked in qp3 I can see they both have the expected values. Any help would be appreciated. thanks

хранимая процедура:
USE [STAFFORDSHIRE_NSG8_1_DVL]
GO
/****** Object:  StoredProcedure [dbo].[WQB_jdtest_shp_0]    Script Date: 16/12/2019 11:13:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[WQB_jdtest_shp_0] 
    @p1 nvarchar(100),  
    @n nvarchar(100) 
AS 
EXEC('
    CREATE VIEW dbo.[' + @n + '] AS 
    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 (Visual Basic):
Using con As SqlConnection = New SqlConnection("Data Source=" + dif.ServerName + ";Initial Catalog=" + dif.DatabaseName + ";Integrated Security=True")
  Using qp3 As SqlCommand = New SqlCommand("WQB_jdtest_shp_0", con)
    qp3.CommandText = "WQB_jdtest_shp_0"
    qp3.CommandType = CommandType.StoredProcedure

    If Not HttpContext.Current.Session("Parameters") Is Nothing Then
       For i = 0 To HttpContext.Current.Session("Parameters").Count - 1
       Dim stringParam = "'" + HttpContext.Current.Session("Parameters")(i).value().ToString() + "'"
       qp3.Parameters.AddWithValue("@p" + (i + 1).ToString(), stringParam)
       Next
    End If

    qp3.Parameters.AddWithValue("@n", "WQB_VIEW_" & name.Replace(" ", "_").Replace(".", "_") & "_" & j)

    con.Open()
    qp3.ExecuteNonQuery()
  End Using
End Using


Что я уже пробовал:

- присвоение параметрам хранимой процедуры значения null
- запись по индивидуальным параметрам
- использование commandType = CommandTypetext, а затем добавление команды exec в виде текста

4 Ответов

Рейтинг:
9

Member 14476420

the solution to my problem was to change this:

Geometry::STGeomFromText(' + '@p1' + ', 0).MakeValid()

to this:

Geometry::STGeomFromText(''' + @p1 + ''', 0).MakeValid()

I had not noticed that @p1 was a string


Richard Deeming

NB: Этот код уязвим для SQL-инъекция[^В то время как воздействие в этом случае ограничено операциями, которые разрешены в представлении, по крайней мере, это откроет уязвимость раскрытия информации.

К сожалению, поскольку представления не принимают параметры, нет очевидного способа исправить это.

Если бы это было возможно, я был бы склонен отказаться от всего этого кода и найти лучшее решение.

Рейтинг:
1

Wendelius

Попробуйте отладить вызывающую сторону. Размещение точки останова в первой строке и выполнение каждой строки кода по очереди должно показать вам, если:
- HttpContext.Current.Session("Parameters") нет ничего. Таким образом, на p1 параметр пустой
- Или HttpContext.Current.Session("Parameters").Count является 0 Это вызвало бы ту же проблему

Если какая либо из этих проблем является проблемой убедитесь что параметры сеанса установлены правильно для вашего HttpContext


Member 14476420

Спасибо,

HttpContext.Current.Session("Parameters")
содержит ожидаемое значение и строки внутри оператора 'if', которые будут поражены

Рейтинг:
1

MadMyche

Вопрос: что произойдет, если Свойство HttpContext.Тока.Сессия("Параметры") неужели ничего?
A: обязательный параметр @p1 не добавляется в команду SQL

If Not HttpContext.Current.Session("Parameters") Is Nothing Then
  For i = 0 To HttpContext.Current.Session("Parameters").Count - 1
    Dim stringParam = "'" + HttpContext.Current.Session("Parameters")(i).value().ToString() + "'"
     qp3.Parameters.AddWithValue("@p" + (i + 1).ToString(), stringParam)
  Next
End If


Member 14476420

Спасибо, я могу это подтвердить

HttpContext.Current.Session("Parameters")
не является ничем и содержит ожидаемое значение

Рейтинг:
0

#realJSOP

Мой совет-сделать это хранимой proc и вызвать его из приложения. По крайней мере, таким образом вы можете запустить его в SSMS и не быть вынужденным запускать свое приложение, чтобы наблюдать, как оно терпит неудачу.