매개 변수가있는 SQL 문에 테이블 반환 매개 변수를 전달할 때 '스칼라 변수를 선언해야 함'오류

존 P

C #에서는 DataTable을 매개 변수로 SQL 문에 전달하려고합니다. 내가 가진 코드는 다음과 같습니다.

protected virtual void DoDeleteRecords(List<Guid> ids)
{   
    if (ids.Count > 0)
    { 
        DataTable tvp = new DataTable();
        tvp.Columns.Add("Id", typeof(Guid));

        foreach (Guid id in ids)
        {
            DataRow row = tvp.NewRow();
            row["Id"] = id;

            tvp.Rows.Add(row);
        }

        string sql = string.Format("DELETE FROM MyTable WHERE ID IN ({0})", "@IDTable");

        SqlConnection connection = new SqlConnection(CoreSettings.ConnectionString);

        using (connection)
        {
            SqlCommand command = new SqlCommand(sql, connection);
            SqlParameter tvpParam = command.Parameters.AddWithValue("@IDTable", tvp);
            tvpParam.SqlDbType = SqlDbType.Structured;
            tvpParam.TypeName = "dbo.IDList";

            connection.Open();

            command.ExecuteNonQuery();

            connection.Close();
        }
    }
}

그러나 command.ExecuteNonQuery가 호출되면 다음 SqlException 오류가 발생합니다.

스칼라 변수 "@IDTable"을 선언해야합니다.

이 오류는 일반적으로 매개 변수 값을 누락하는 것과 관련이 있음을 이해하지만 내가 알 수있는 한 알고 있습니다.

아무도 내가 뭘 잘못하고 있는지 볼 수 있습니까?

감사합니다.

업데이트 내 예제에서 엉뚱한 SQL 주입이 풍부한 코드를 제거하기 위해 질문을 수정했습니다.

Charlieface

중요한 것부터 먼저 : 나는 당신이 점점 아무 생각이 없다 tableName등을 columnName, 그러나 사용자가 제공 한 경우, 다음이 SQL 주입 열려 있습니다. 최소한 QUOTENAME()실제 코드가 삽입되지 않도록 하려면 사용하십시오 .

둘째, 실제로 TVP를 사용하지 않습니다. 당신이 가지고있는 코드 IN (@IDTable)는 TVP를 사용하는 방법이 아니라는 것입니다.

TVP는 테이블 변수 일 뿐이며 다른 테이블과 마찬가지로 사용해야합니다.

protected virtual void DoDeleteRecords(string tableName, string idColumnName, List<Guid> ids)
{   
    if (ids.Count > 0)
    { 
        DataTable tvp = new DataTable();
        tvp.Columns.Add("Id", typeof(Guid));

        foreach (Guid id in ids)
        {
            DataRow row = tvp.NewRow();
            row["Id"] = id;

            tvp.Rows.Add(row);
        }

        const string sql = @"
DECLARE @sql nvarchar(max) =
'DELETE FROM ' +
QUOTENAME(@tableName) +
' WHERE ' +
QUOTENAME(@idColumnName) +
' IN (SELECT * FROM @IDTable);';

EXEC sp_executesql @sql,  N'@IDTable dbo.IDList', @IDTable =@IDTable;
";

        using(SqlConnection connection = new SqlConnection(CoreSettings.ConnectionString))
        using(SqlCommand command = new SqlCommand(sql, connection))
        {
            
            SqlParameter tvpParam = command.Parameters.AddWithValue("@IDTable", tvp);
            tvpParam.SqlDbType = SqlDbType.Structured;
            tvpParam.TypeName = "dbo.IDList";
            command.Parameters.Add("@tableName", SqlDbType.NVarChar, 128).Value = tableName;
            command.Parameters.Add("@idColumnName", SqlDbType.NVarChar, 128).Value = idColumnName;
            connection.Open();

            command.ExecuteNonQuery();

            connection.Close();
        }
    }
}

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사