通过SQL存储过程填充DataTable会产生数据,但仅当参数没有Apostrophe /单引号时才会生成数据

时间:2016-03-17 19:10:44

标签: c# sql-server stored-procedures

我传递给存储过程以填充我的DT的一个参数是电子邮件地址。如果电子邮件地址有('),那么DT将填充没有数据。

但是,我确实逃过了(')所以我知道这不太可能是问题所在:

  • 使用相同参数运行存储过程本身会返回正确的行数。
  • 使用参数without(')从代码运行存储过程会返回正确的行数

我想为什么('')或('''')的存在会导致调用不成功,即使存储过程运行?如果我有办法解决这个问题?

我尝试的事情:

  • 在为参数赋值之前转义'

    if (searchTermValue.Contains('\''))
        searchTermValue = searchTermValue.Replace("'", "''''");  
    
  • 在SQL存储过程中转义('):

    SET @searchTerm = REPLACE(@searchTerm,CHAR(39), CHAR(39) + CHAR(39) + CHAR(39) + CHAR(39))
    

当我从代码中调用它时,我仍然无法使存储过程返回数据。当@searchTerm有'。对存储过程的调用是标准的:

 {    SqlCommand cmd = new SqlCommand();
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = "rpt_EmailSearch";
            cmd.Parameters.Add(new SqlParameter("@FilterBy", string.Empty));
            cmd.Parameters.Add(new SqlParameter("@FilterType", FilterType));
            cmd.Parameters.Add(new SqlParameter("@searchTerm", searchTerm));
            cmd.Parameters.Add(new SqlParameter("@BaseChannelID", BaseChannelID));
            cmd.Parameters.Add(new SqlParameter("@currentPage", currentPage));
            cmd.Parameters.Add(new SqlParameter("@pageSize", pageSize));
            cmd.Parameters.Add(new SqlParameter("@SortBy", sortColumn + " " + sortDirection));

            return DataFunctions.GetDataTable(cmd, DataFunctions.ConnectionString.Communicator.ToString());}

public static DataTable GetDataTable(SqlCommand cmd,string connectionStringName)     {         DataTable dt = new DataTable();

    using (SqlConnection conn = DataFunctions.GetSqlConnection(connectionStringName))
    {
        cmd = MinDateCheck(cmd);
        cmd = MinTimeCheck(cmd);
        cmd.Connection = conn;
        cmd.CommandTimeout = 0;

        try
        {
            cmd.Connection.Open();
            SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            dt.Load(dr);
        }
        catch (Exception)
        {                    
            throw;
        }
        finally
        {
            if (cmd != null)
            {
                cmd.Connection.Close();
                cmd.Dispose();
            }
        }
    }

    return dt;
}

这是proc本身:

 declare
  --Payload filters
      @FilterBy varchar(50) = '',
      @FilterType varchar(50) = 'like',
      @searchTerm varchar(MAX) = '', ---THIS IS THE PARAMETER WHERE I SUPPLY 'o'test@mail.com' VALUE
      @BaseChannelID int = 92,
     --Sort filters
      @CurrentPage int = 1,
      @PageSize int = 15,
    @SortBy VARCHAR(30) = 'EmailAddress DESC',
    --Local variables
      @EmailPart varchar(MAX) = '',
      @ChannelPartOne varchar(MAX) = '',
      @ChannelPartTwo varchar(MAX) = ''    

SET @searchTerm = REPLACE(@searchTerm,CHAR(39), CHAR(39) + CHAR(39) + CHAR(39) + CHAR(39))


  IF @FilterType = 'equals'
  BEGIN
    SET @EmailPart = 'AND e.EmailAddress = ''' + @searchTerm + ''''
  END
  IF @FilterType = 'starts'
  BEGIN
    SET @EmailPart = 'AND e.EmailAddress like ''' + @searchTerm + '%'''
  END
  IF @FilterType = 'like'
  BEGIN
    SET @EmailPart = 'AND e.EmailAddress like ''%' + @searchTerm + '%'''
  END
  IF @FilterType = 'ends'
  BEGIN
    SET @EmailPart = 'AND e.EmailAddress like ''%' + @searchTerm + ''''
  END

  IF @BaseChannelID <> 0
  BEGIN
    SET @ChannelPartOne = 'AND bc.BaseChannelID = ' + CONVERT(varchar(10), @BaseChannelID)
    SET @ChannelPartTwo = 'AND e.BaseChannelID = ' + CONVERT(varchar(10), @BaseChannelID)
  END


  CREATE TABLE #tmp (
    BaseChannelName varchar(100),
    CustomerName varchar(100),
    GroupName varchar(100),
    EmailAddress varchar(100),
    SubscribeTypeCode varchar(100),
    DateCreated datetime,
    DateModified datetime
  )

  EXEC ('     
            INSERT INTO #tmp
            select 
                  bc.BaseChannelName, 
                             c.CustomerName, 
                             g.GroupName, 
                             e.EmailAddress, 
                  case when eg.SubscribeTypeCode = ''S''  then ''Subscribed'' 
                             when eg.SubscribeTypeCode = ''U'' then ''Unsubscribed'' 
                             when eg.SubscribeTypeCode = ''P'' then ''Pending'' 
                             when eg.SubscribeTypeCode = ''D'' then ''Bad Record'' 
                             when eg.SubscribeTypeCode = ''M'' then ''Master Suppressed'' else eg.SubscribeTypeCode end as ''Subscribe'', 
                  eg.CreatedOn as ''DateCreated'', eg.LastChanged as ''DateModified''
                  from
                  Emails e with (nolock)
                  join ECN5_ACCOUNTS..Customer c with (nolock) on e.CustomerID = c.CustomerID and c.IsDeleted = 0
                  join ECN5_ACCOUNTS..Basechannel bc with (nolock) on c.BaseChannelID = bc.BaseChannelID and bc.IsDeleted = 0
                  join EmailGroups eg with (nolock) on e.EmailID = eg.EmailID
                  join Groups g with (nolock) on eg.GroupID = g.GroupID and IsNull(g.MasterSupression, 0) = 0
            where
                  1=1
                  ' + @ChannelPartOne + '
                  ' + @EmailPart + '

            UNION

            select 
                  bc.BaseChannelName, '''' as ''CustomerName'', '''' as ''GroupName'', EmailAddress, ''Channel Suppressed'' as ''Subscribe'', e.CreatedDate as ''DateCreated'', e.UpdatedDate as ''DateModified''
            from
                  ChannelMasterSuppressionList e with (nolock)
                  join ECN5_ACCOUNTS..Basechannel bc with (nolock) on e.BaseChannelID = bc.BaseChannelID and bc.IsDeleted = 0
            where
                  e.IsDeleted = 0
                  ' + @ChannelPartTwo + '
                  ' + @EmailPart + '
            order by ' + @SortBy
  );

  WITH Results
  AS (SELECT
    ROW_NUMBER() OVER (ORDER BY @SortBy
    ) AS ROWNUM,
    COUNT(*) OVER () AS TotalCount,
    *
  FROM #tmp)
  SELECT
    *
  FROM Results
  WHERE ROWNUM BETWEEN ((@CurrentPage - 1) * (@PageSize + 1)) AND (@CurrentPage * @PageSize)
  DROP TABLE #tmp
END

一个更多的更正:这个不运行动态SQL的proc版本运行速度非常慢(动态SQL大约需要6秒,没有动态SQL大约需要150秒)所以我现在必须恢复到上面的版本。

谢谢!

1 个答案:

答案 0 :(得分:0)

好的,弄明白为什么没有回来: 当执行命令时,(&#39;)被自动替换为(&#39;&#39;)所以在代码中执行替换会创建在任何地方找不到匹配项的参数D B。 但是,我必须在SQL中执行Replace,如下所示;因为否则动态SQL不能形成proc:

SET @searchTerm = REPLACE(@searchTerm,CHAR(39), CHAR(39) + CHAR(39))

我的错误是我不知道sql命令的自动替换。 谢谢大家的回答!