You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET应用中如何正确向SQL存储过程传递nvarchar参数?

问题描述

执行带参数的SQL存储过程时,传递名为office的nvarchar参数遇到困难。直接在MS SQL中执行存储过程时,给参数加双单引号才能生效,但在C#代码中同样添加双单引号后仍无法正常运行,报错:

Incorrect Syntax near 'Nord'.

即使去掉代码中的双单引号,或者传递不含空格的参数,错误依然存在。

相关代码

C#调用代码

parameters.Add("office", "''Niederlassung Nord''"); //<---问题所在
parameters.Add("year", "2023");
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[sqlConn];

using (SqlConnection conn = new SqlConnection(settings.ConnectionString))
{
    using (SqlCommand storedCmd = new SqlCommand(sql, conn))
    {
        conn.Open();
        storedCmd.CommandType = CommandType.StoredProcedure;
        storedCmd.CommandTimeout = 1200;
        if (parameters != null)
        {
            foreach (KeyValuePair<string, object> value in parameters)
            {
                storedCmd.Parameters.AddWithValue("@" + value.Key, value.Value);
            }
        }

        using (SqlDataReader reader = storedCmd.ExecuteReader())
        {
            while (reader.HasRows)
            {
                while (reader.Read())
                {
                    Dictionary<string, string> row = new Dictionary<string, string>();
                    for (var i = 0; i < reader.FieldCount; i++) // 单个字段
                    {
                        row.Add(reader.GetName(i), reader[i].ToString());//getname用于获取列名
                    }
                    currentList.Add(row);
                }
            }             
        }
    }
}

直接在SQL中执行的有效语句

USE [ServerName]
GO

DECLARE @return_value int

EXEC    @return_value = [dbo].[GetData]
        @office = N'''Niederlassung Nord''', //<-- 只有这样加双单引号才生效
        @year= N'2023'

SELECT  'Return Value' = @return_value

GO

存储过程核心代码

USE [ServerName]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[GetData]
  @office nvarchar(4000) = null,
  @year nvarchar(4) = null
AS
BEGIN
CREATE TABLE #masterData2 (
    [office] [nvarchar](40) NULL,
)
...
  if (@office is not null)
        begin
            if (@sql1 is not null)
                select @sql1 += ' AND #masterData2.[office ] in (' + @office + ')'
            else
                select @sql1 = ' #masterData2.[office ] in (' + @office + ')'
        end
...
解决方法

问题根源在于存储过程使用了动态SQL拼接,且未正确处理参数,直接将@office参数拼入SQL语句导致语法错误。以下是两种解决方式:

方法一:修改存储过程,使用参数化动态SQL(推荐)

彻底避免字符串拼接,改用参数化动态SQL,既解决语法问题,还能防范SQL注入:

ALTER PROCEDURE [dbo].[GetData]
  @office nvarchar(4000) = null,
  @year nvarchar(4) = null
AS
BEGIN
CREATE TABLE #masterData2 (
    [office] [nvarchar](40) NULL,
)
...
DECLARE @sql1 NVARCHAR(MAX) = '';
-- 处理office参数
IF (@office IS NOT NULL)
BEGIN
    IF (@sql1 <> '')
        SET @sql1 += ' AND #masterData2.[office] IN (@officeParam)'
    ELSE
        SET @sql1 += ' #masterData2.[office] IN (@officeParam)'
    
    -- 执行动态SQL时传入参数
    EXEC sp_executesql @sql1, N'@officeParam NVARCHAR(4000)', @officeParam = @office
END
...

同时,C#代码直接传递原始字符串即可,无需额外加单引号:

parameters.Add("office", "Niederlassung Nord"); // 直接传原始字符串

方法二:保留原存储过程逻辑(临时方案,不推荐)

若无法修改存储过程,需在C#中传递符合IN子句格式的字符串,注意正确转义单引号:

// 单个值时,传递带单引号的字符串(用双单引号转义)
parameters.Add("office", "'Niederlassung Nord'"); 
// 多个值时,格式为"'值1','值2'",比如:"'Niederlassung Nord','Niederlassung Süd'"

此方式存在SQL注入风险,仅作临时应急使用。


内容的提问来源于stack exchange,提问作者user2018

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 18:57:45