【问题标题】:Running stored procedure in vb.net results in "invalid column name"在 vb.net 中运行存储过程会导致“列名无效”
【发布时间】:2020-04-09 11:44:27
【问题描述】:

我正在尝试在 vb.net 应用程序中执行带有参数的存储过程,并不断收到错误

System.Data.SqlClient.SqlException: '无效的列名'r'

我试图找到解决方案,但很多问题似乎都与插入数据有关,而我只是在尝试读取数据。

我只是不确定我试图引用“r”作为列名的原因是什么?结果将导出到表单上的 DataGrid 框中。

代码:

Private Function GetResults() As DataTable
    Dim dtAccounts As New DataTable
    Dim connString As String = ConfigurationManager.ConnectionStrings("PBSQL").ConnectionString
    Dim CountDoc As String = "rqs.service_id,svc.service_abbrev,do.doctor_id,do.dr_first_name,do.dr_surname"
    Dim NoCountDoc As String = "rqs.service_id,svc.service_abbrev"

    Using conn As New SqlConnection(connString)
        Using cmd As New SqlCommand("EXEC dbo.aslGetCommonv1 @StartDate, @EndDate, @GroupBy", conn)

            cmd.Parameters.Add("@StartDate", SqlDbType.Date).Value = dateFrom.Value
            cmd.Parameters.Add("@EndDate", SqlDbType.Date).Value = dateTo.Value

            If cb_SearchByDoc.Checked = True Then
                cmd.Parameters.Add("@GroupBy", SqlDbType.VarChar).Value = CountDoc
            Else
                cmd.Parameters.Add("@GroupBy", SqlDbType.VarChar).Value = NoCountDoc
            End If

            conn.Open()

            Dim reader As SqlDataReader = cmd.ExecuteReader()
            dtAccounts.Load(reader)

        End Using
    End Using

Process:
    Return dtAccounts

End Function

Private Sub BtnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
    dgResults.DataSource = GetResults()
End Sub

这是 SQL 中的过程:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[aslGetCommonv1]
    @StartDate varchar,
    @EndDate varchar,
    @GroupBy varchar
AS
    DECLARE @SQL VARCHAR(MAX)
    SET NOCOUNT ON;
    SET @SQL = 'SELECT rqs.service_id,svc.service_abbrev,do.doctor_id,do.dr_first_name,do.dr_surname,
    COUNT(*) AS total
    FROM dbo.requests_services rqs
    LEFT JOIN services svc ON svc.service_id = rqs.service_id
    LEFT JOIN requests rq ON rq.request_id = rqs.request_id
    LEFT JOIN doctors do ON do.doctor_id  = rq.doctor_id
    WHERE rq.entry_date BETWEEN ' + @StartDate + ' AND ' + @EndDate + ' AND svc.service_id BETWEEN 1005 And 1008 Or svc.service_id = 1401 Or svc.service_id = 1402 Or svc.service_id = 1404 Or svc.service_id = 1405
        OR svc.service_id = 1407 OR svc.service_id = 1408 OR svc.service_id = 1410 OR svc.service_id = 1501 OR svc.service_id BETWEEN 1503 AND 1506 OR svc.service_id = 1509
        OR svc.service_id BETWEEN 5101 AND 5103 OR svc.service_abbrev = ''SADREN'' OR svc.service_abbrev = ''SADREN2'' OR svc.service_abbrev = ''SFH28'' OR svc.service_abbrev = ''SLPSAL''
        OR svc.service_abbrev = ''TFT'' OR svc.service_abbrev = ''CTA'' OR svc.service_abbrev = ''VITD'' OR svc.service_abbrev = ''U216 OH'' OR svc.service_abbrev = ''U2416 OH''
        OR svc.service_abbrev = ''UEMET'' OR svc.service_abbrev = ''CALP'' OR svc.service_abbrev = ''FAEPCR'' OR svc.service_abbrev = ''CDSA1'' OR svc.service_abbrev = ''CDSA2'' 
        OR svc.service_abbrev = ''CDSA3'' OR svc.service_abbrev = ''CDSA3+'' OR svc.service_abbrev = ''CDSA4'' OR svc.service_abbrev = ''CDSA4+'' OR svc.service_abbrev = ''CDSA5''
        OR svc.service_abbrev = ''INTPERM'' OR svc.service_abbrev = ''SIBO2'' OR svc.service_abbrev = ''SIBO3'' OR svc.service_abbrev = ''GIEFFCO'' OR svc.service_abbrev = ''GIEFFME'' OR svc.service_abbrev = ''CMAP''
        OR svc.service_abbrev = ''CMMR'' OR svc.service_abbrev = ''IGA96'' OR svc.service_abbrev = ''IGA96AS'' OR svc.service_abbrev = ''IGG144'' OR svc.service_abbrev = ''IGA144'' OR svc.service_abbrev = ''IGG208''
        OR svc.service_abbrev = ''IGA208'' OR svc.service_abbrev = ''IGG+A208'' OR svc.service_abbrev = ''ALC050'' OR svc.service_abbrev = ''ALC100'' OR svc.service_abbrev = ''ALC150'' OR svc.service_abbrev = ''ALC200''
        OR svc.service_abbrev = ''ALCPLAT'' OR svc.service_abbrev = ''CYTOK'' OR svc.service_abbrev = ''HIAM'' OR svc.service_abbrev = ''DAO'' OR svc.service_abbrev = ''KRPR'' OR svc.service_abbrev = ''ENEUM'' OR svc.service_abbrev = ''LIPOSCRN''
        OR svc.service_abbrev = ''INEUM'' OR svc.service_abbrev = ''ANEUM'' OR svc.service_abbrev = ''ORGANIX'' OR svc.service_abbrev = ''UIODL'' OR svc.service_abbrev = ''MTHFR'' OR svc.service_abbrev = ''OM3INPR''
        OR svc.service_abbrev = ''ONCOSTAT'' OR svc.service_abbrev = ''ONCONEXT'' OR svc.service_abbrev = ''ONCONPLUS'' OR svc.service_abbrev = ''ONCOTRACE'' OR svc.service_abbrev = ''ONCOTRAIL'' OR svc.service_abbrev = ''ONCOCOUNT''
        OR svc.service_abbrev = ''IMMUNOSTAT'' OR svc.service_abbrev = ''NAGALASE'' OR svc.service_abbrev = ''PRIMESPOT'' OR svc.service_abbrev = ''CHEMOSNIP''
    GROUP BY ' + ' ' + @GroupBy + '
    ORDER BY rqs.service_id ASC'

    EXEC(@SQL)

【问题讨论】:

  • 为什么GROUP BY 是动态的,而SELECT 不是?这甚至需要动态 SQL 吗?
  • 大部分左连接在逻辑上都是内连接。那长长的“或”比较列表 - 只需将其转换为等效的 IN 构造,以使您的代码更易于阅读和维护。您尝试动态更改分组将不起作用。这个计数看起来很可疑。请 - 寻求帮助。
  • @Larnu - 我很尴尬我没有意识到这一点,Group By 确实需要是动态的,因此 Select 也是如此,所以我需要改变它。跨度>
  • @SMor 我看过 IN 函数,但不太明白它的意思。然而,我今天再次尝试并成功了。感谢您的意见:)

标签: sql-server vb.net stored-procedures parameters


【解决方案1】:

问题是您将存储过程参数定义为 varchar - 没有指定长度。

NOT 指定了所需长度的 varchar - 默认长度为 1 个字符 - 因此,如果您传入任何以 @ 开头的字符串987654323@,它将被截断R .....

因此,strong 建议是:始终 为 T-SQL 中的 varchar 参数和/或变量定义一个显式长度

另外:如果您传入日期 - 建议使用最合适的数据类型 - 在这种情况下不是 varchar,而是 DATEDATETIME2(n) .....

所以试试这个:

ALTER PROCEDURE [dbo].[aslGetCommonv1]
    @StartDate DATE,
    @EndDate DATE,
    @GroupBy VARCHAR(100)

我还强烈建议在调用此存储过程的 VB.NET 代码中定义该长度:

cmd.Parameters.Add("@GroupBy", SqlDbType.VarChar, 100).Value = CountDoc
                                                ^^^^^^

【讨论】:

  • 您还需要向 OP 解释如何在此处参数化动态 SQL 并安全地注入值。他们现在有一个重要的安全会议。
  • 哎呀;关注*
  • "默认长度为 1 个字符 - 因此,如果您传入任何以 R........开头的字符串,它将被截断为 R ....."这不是真的!是的,最好包含字段大小,但只有长度超过数据库中字段大小的字符串才会丢失数据。
  • 谢谢@marc_s!这正是问题所在。我确信上次我做这样的事情时不是这种情况(可能是 10 年前的好事情),但我显然错了。现在解决我的存储过程中的错误...
  • @Mary: 同意 - 我也喜欢 .Add() 而不是 .AddWithValue,在这种情况下使用 .Add 方法,事实上,省略 varchar 长度不会导致我的问题描述。为清楚起见提供它仍然是一个好习惯 - 但如果您在实际 SQL 代码中这样做,则将其忽略并不像它那样有害
猜你喜欢
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 2021-08-02
  • 1970-01-01
  • 2020-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多