1

C# の t-sql 選択クエリで問題が発生しています。クエリは次のとおりです。

@"SELECT * FROM 
 (SELECT *, ROW_NUMBER() OVER (ORDER BY id) as row_number
 FROM [mytable]) t0
 WHERE row_number BETWEEN @skip and @take
 AND
 uploadDate IN (@years) 
 AND NOT photoId IN (@shownPhotos) 
 ORDER BY NEWID()";

cmd.Parameters.Add("@skip", SqlDbType.Int).Value = skip;
cmd.Parameters.Add("@take", SqlDbType.Int).Value = take;
cmd.Parameters.Add("@shownPhotos", SqlDbType.VarChar).Value = shownPhotos;
cmd.Parameters.Add("@years", SqlDbType.VarChar).Value = years;

このメソッドは、skip count、take count、shownPhotos (写真 ID を含むカンマ区切りの文字列)、years (写真を表示する年を含むカンマ区切りの文字列) の 4 つのパラメータを取ります。

したがって、基本的には、コンマ区切りの文字列のいずれかの年に一致し、まだ表示されていないデータベースから写真を返す必要があります。

問題 (私が思うに) は、パラメーターが文字列であるため、'1234,567,890' および '2011,2012' として解釈されることです。を使用せずに SQL サーバー管理ツールでクエリを実行すると、正常に動作します。

誰かがこれに対する回避策を持っていますか? :-)

よろしくお願いします!

更新されたコード:

// Create datatables
            DataTable yearsTable = new DataTable();
            yearsTable.Columns.Add("YearID", typeof(string));
            yearsTable.Columns.Add("Year", typeof(string));

            foreach(string year in years.Split(','))
                yearsTable.Rows.Add(new object[] { year, year });

            using (var conn = new SqlConnection(GlobalSettings.DbDSN))
            {
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText =
                        @"SELECT * FROM 
                          (SELECT *, ROW_NUMBER() OVER (ORDER BY id) as row_number
                          FROM [mytable]) t0
                          WHERE row_number BETWEEN @skip and @take
                          AND
                          uploadedDate IN (@years)                               
                          ORDER BY NEWID()";

                    SqlParameter skipParam = cmd.Parameters.AddWithValue("@skip", skip);
                    skipParam.SqlDbType = SqlDbType.Int;

                    SqlParameter takeParam = cmd.Parameters.AddWithValue("@take", take);
                    takeParam.SqlDbType = SqlDbType.Int;

                    SqlParameter yearsParam = cmd.Parameters.AddWithValue("@years", yearsTable);
                    yearsParam.SqlDbType = SqlDbType.Structured;
                    yearsParam.TypeName = "dbo.MyTableType";


                    var reader = cmd.ExecuteReader();                        
                }
4

3 に答える 3

2

あなたの問題の評価は正しいです - @shownphotos と @years は単一の文字列として解釈されます。

テーブル値パラメーターが答えです

http://msdn.microsoft.com/en-us/library/bb675163.aspx

(SQL ステートメントのパラメーター化はうまくいきました。文字列から SQL ステートメントを連結して、この問題を回避しようとしないでください!)

于 2012-10-18T12:40:29.460 に答える
1

実際、あなたINは「この1つの値のセットにある」と解釈されています。つまり、あなたが持っているものは次のものと同じです:

AND uploadDate = @years
AND NOT photoId = @shownPhotos

'1234,567,890'は、文字列およびで通常の文字列等価として評価されます'2011,2012'。TSQL レベルでは、単一の varchar を複数の行の値に分割する「分割」UDF を記述するのが一般的な方法です。多くのライブラリにもこのためのツールがあります。たとえば、「dapper」では、それらを事前に展開するための構文トリックを追加します。

int[] years = {2011,2012};
int[] shownPhotos = {1234,567,890};
int skip = 0, take = 10;
var rows = connection.Query<RowType>(
  @"SELECT * FROM 
   (SELECT *, ROW_NUMBER() OVER (ORDER BY id) as row_number
   FROM [mytable]) t0
   WHERE row_number BETWEEN @skip and @take
   AND uploadDate IN @years
   AND NOT photoId IN @shownPhotos
   ORDER BY NEWID()", new {skip,take,years,shownPhotos}).ToList();

の横に括弧がないことに注意しINてください。これは、ライブラリに対して「これを自分で理解する」と解釈され、ライブラリはまさにあなたが望むことを行います。実際には次のように評価されます。

   AND uploadDate IN (@years0,@years1)
   AND NOT photoId IN (@shownPhotos0,@shownPhotos1,@shownPhotos2)

where @years0has value 2011@years1has the value2012など。

于 2012-10-18T12:44:41.450 に答える
-1

日付全体を一連の年と比較しているようです。

年だけ抽出して比較してみませんか?

@"SELECT * FROM 
(SELECT *, ROW_NUMBER() OVER (ORDER BY id) as row_number
FROM [mytable]) t0
WHERE row_number BETWEEN @skip and @take
AND
DATEPART(yyyy,uploadDate) IN (@years) 
AND NOT photoId IN (@shownPhotos) 
ORDER BY NEWID()";

DATEPART の詳細については、http ://www.w3schools.com/sql/func_datepart.asp をご覧ください。

于 2012-10-18T12:47:05.593 に答える