尝试在使用DECLARE语句时从asp.net传递参数但是收到错误说"必须声明标量变量" @pID"

时间:2016-05-15 05:48:49

标签: asp.net sql-server tsql scalar sqlparameters

我有一个名为ReportValues的表,它存储关键字和值对中玩家的所有信息。该表具有另一个名为Reports的表中的外键。我试图在每个报告的一行中获取所有数据,其中键将是列名称,值将填充返回的表。如果我手动插入@pID而不是作为参数,那么代码可以工作,但是当使用参数时我得到以下错误:"必须声明标量变量" @pID" 。这是我的代码:

public DataTable getBarChartData(int p_ID)        
{
    //this query is transposing rows into columns as each key gets a column and the grouping variable is RV.report
    string sqlQuery = "DECLARE @keyName AS VARCHAR(MAX) ";
    sqlQuery += "SELECT @keyName = ";
    sqlQuery += "COALESCE(@keyName + ', ', '') + CAST(keyName AS VARCHAR(20)) ";
    sqlQuery += "FROM(SELECT DISTINCT keyname FROM ReportValues) ActivePlayers ";
    sqlQuery += "SELECT @keyName keyNames ";
    sqlQuery += "DECLARE @DynamicPIVOT AS VARCHAR(MAX) ";
    sqlQuery += "SELECT @DynamicPIVOT = 'SELECT ' + @keyName + ";
    sqlQuery += "' FROM ( ";
    sqlQuery += "SELECT RV.report, RV.keyname, RV.value FROM ReportValues RV ";
    sqlQuery += "join ReportValues RV1 on RV.report = RV1.report ";
    sqlQuery += "join ReportValues RV2 on RV.report = RV2.report ";
    sqlQuery += "where RV1.value <> 1 and RV1.keyName = ''SessionStage'' and RV2.value =  @pID and RV2.keyName = ''PId'' and RV.report in ( ";
    sqlQuery += "SELECT id FROM Reports r ";
    sqlQuery += "WHERE r.timeStamp >= dateadd(hour, -240, GETDATE()) ";
    sqlQuery += ") ";
    sqlQuery += ") ActivePlayers";
    sqlQuery += "PIVOT(";
    sqlQuery += "MAX(value) FOR keyname IN(' + @keyName + ') ";
    sqlQuery += ") Result; ' ";
    sqlQuery += "EXEC(@DynamicPIVOT) ";
    int pID = p_ID;
    //this passes the query and param to an execution function
    DataTable dtLabels = GetBarChartDataByUser(sqlQuery, pID);
    return dtLabels;
}

//this is the sql execution function
public DataTable GetBarChartDataByUser(string strQuery, int pID)
{
    SqlConnection con = new SqlConnection(createConnectionReadOnly());
    con.Open();
    try
    {

        SqlCommand cmd = con.CreateCommand();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = strQuery;
        cmd.Parameters.AddWithValue("@pID", pID);
        SqlDataAdapter dap = new SqlDataAdapter(cmd);
        //here is where I get the error
        DataSet ds = new DataSet();
        dap.Fill(ds);
        return ds.Tables[0];
    }
    catch (Exception ex)
    {

    }
    finally
    {
        if (con.State == ConnectionState.Open)
        {
            con.Close();
        }
    }
    return null;

}

1 个答案:

答案 0 :(得分:1)

&#34;和RV2.value = @ pID&#34;是动态字符串的一部分,在动态字符串构建查询中不被视为变量。在SQL Server中,变量范围仅扩展到当前正在执行的批处理或函数,因此在&#34; EXEC()&#34;内执行动态构建的代码。不知道变量@pID 您可以通过几种方式解决问题,其中一种方法如下:

sqlQuery += "join ReportValues RV2 on RV.report = RV2.report ";
sqlQuery += "where RV1.value <> 1 and RV1.keyName = ''SessionStage'' and RV2.value =  @pID and RV2.keyName = ''PId'' and RV.report in ( ";
sqlQuery += "SELECT id FROM Reports r ";

sqlQuery += "join ReportValues RV2 on RV.report = RV2.report ";
sqlQuery += "where RV1.value <> 1 and RV1.keyName = ''SessionStage'' and RV2.value =  ' + CONVERT( VARCHAR, @pID ) + ' and RV2.keyName = ''PId'' and RV.report in ( ";
sqlQuery += "SELECT id FROM Reports r ";

(注意&#39; + @pID +&#39;)

另一个(我认为更好的方法)是取代:

"EXEC(@DynamicPIVOT) "

"EXEC sp_executesql @DynamicPIVOT, N'@pID INT', @pID "

注意: @DynamicPIVOT必须声明为NVARCHAR(MAX)
注2:将@pID声明为与RV2.keyName相同的数据类型。这将避免在查询执行期间进行类型转换

为了帮助将来诊断类似的问题,我建议您在执行之前检查sqlQuery的值并将其粘贴到SQL Management Studio中。 这将清楚地表明哪些部分是字符串以及哪些部分是SQL可执行代码。