0

私は6つのドロップダウンボックスでフィルタリングできるグリッドビューを持っているので、ドロップダウンに選択やnullなどがある場合、SQLを書くときに最も簡単な方法は「or」ステートメントを使用することです.

ただし、SQLまたはステートメントを使用することは悪い考えであるとここや他のサイトで読んだことがありますが、各ddl選択がnullであるかどうかについてバリエーションを書くのではなく、他の提案を提供できますか? 以下は、すべての ddl が値を返す最初のクエリの例です。

@ruleID int = null, 
@engagementStatusID int = null,
@areaOfWorkID int = null,
@registered bit = null,
@staffGroupID int = null,
@assignmentTypeID int = NULL

AS
SET NOCOUNT ON

IF (@ruleID IS NOT NULL and @engagementStatusID IS NOT NULL and @areaOfWorkID IS NOT NULL and 
        @registered IS NOT NULL and @staffGroupID IS NOT NULL and @assignmentTypeID IS NOT NULL)

BEGIN
    SELECT            r.dbRuleId AS RuleID,r.dbEngagementStatusId AS EngagementStatusID, 
                  r.dbIsAllStaffGroups AS AllStaffGroups,r.dbIsAllAssignments AS AllAssignments, 
                  r.dbIsAllRegistered AS AllRegistered,r.dbIsAllUnregistered AS AllUnregistered, 
                  r.dbSoftDelete AS Softdelete, es.dbName AS EngagementName, 
                  sgc.dbName AS StaffGroupName, aow.dbName AS AreaOfWorkName, 
                  at.dbName AS AssignmentName, at.dbIsRegistered AS Registered,sgc.dbStaffGroupCodeId AS StaffGroupCodeID, 
                  at.dbAssignmentTypeId AS AssignmentID, aow.dbAreaOfWorkId AS AreaOfWorkID
FROM              dbo.tbRule r INNER JOIN
                  dbo.EngagementStatus es ON r.dbEngagementStatusId = es.dbEngagementStatusId INNER JOIN
                  dbo.RuleStaffGroup rsg ON r.dbRuleId = rsg.dbRuleId INNER JOIN
                  dbo.StaffGroupCode sgc ON rsg.dbStaffGroupId = sgc.dbStaffGroupCodeId INNER JOIN
                  dbo.RuleAssignmentCode rac ON r.dbRuleId = rac.dbRuleId INNER JOIN
                  dbo.AssignmentCode ac ON 
                  rac.dbAssignmentCodeId = ac.dbAssignmentCodeId INNER JOIN
                  dbo.AssignmentType at ON ac.dbAssignmentId = at.dbAssignmentTypeId INNER JOIN
                  dbo.AreaOfWork aow ON ac.dbAreaOfWorkId = aow.dbAreaOfWorkId
    WHERE   ((r.dbRuleId = @ruleID) and (r.dbEngagementStatusId = @engagementStatusID) and (aow.dbAreaOfWorkId = @areaOfWorkID) and
                (at.dbIsRegistered = @registered) and (sgc.dbStaffGroupCodeId = @staffGroupID) and (at.dbAssignmentTypeId = @assignmentTypeID))

これに関するアドバイスは素晴らしいでしょう

更新私は自分のコードについて何かを明確にする必要があると感じています.nullと言うと、これはドロップダウンリストの「すべて」の選択に割り当てた値です。たとえば、ほとんどの場合、値を取得するためにこのようなことを行いますDBに渡す必要がある

int? Type = (this.ddlType.SelectedValue.ToString() == "All") ? (int?)null : Convert.ToInt32(this.ddlType.SelectedValue.ToString());

したがって、ユーザーがすべての Db 受信を選択した場合、「null」を受け取り、「if @blah IS NOT NULL」などで使用できます。これはおそらくこれを行うための最良の方法ではないことに気付きました

4

3 に答える 3

1

次のようなことをすると問題が発生します。

WHERE   (r.dbRuleId = @ruleID or @ruleID is null)
and     (r.dbEngagementStatusId = @engagementStatusID
                 or @engagementStatusID is null)
-- ... lots more

これはすぐに非常に悪いクエリ プランに劣化します。秘訣は、クエリ パラメータのセットと正確に一致する TSQL を用意することです。

これを修正する方法を維持するのが難しいのは、すべての可能性に対して DML を記述し、正しいものに分岐することですが、これは非常に見苦しく、多くのツールを混乱させます。

これを行う最も簡単な方法は、呼び出し元で TSQL を適切に構築することです。ただし、システムがストアド プロシージャを使用することを要求する場合 (最近の利点はせいぜい疑わしいです - ところで)、最も簡単な選択は動的です。 SQL。明らかに、ここで注意する必要があります-(インジェクションとクエリプランの両方の理由で)入力を連結したくないのですが、-次のようなことができます:

declare @sql nvarchar(4000) = N'...start of query...';

if(@ruleID is not null)
    set @sql = @sql + N' and r.dbRuleId = @ruleID';
if(@engagementStatusID is not null)
    set @sql = @sql + N' and r.dbEngagementStatusId = @engagementStatusID';

sp_executesql次に、パラメータを宣言して、それを実行する必要があります。

exec 'sp_executesql', @sql,
      N'@ruleID int, @engagementStatusID int',
      @ruleID, @engagementStatusID
于 2013-10-02T09:42:49.213 に答える
1

このストアド プロシージャを実行してから、データベース レベルでユーザー入力を検証しているようです。ドロップダウン リストの値が の場合は、データベース ストアド プロシージャを呼び出さないnullでください。これは、クライアント側 (またはサーバー側) で処理できます。

クライアント側 (JavaScript) の方がユーザー エクスペリエンスに適しているため、ユーザーが適切なドロップダウン リストの値をすべて選択している場合は、ストアド プロシージャを呼び出すことができます。

于 2013-10-02T09:26:02.057 に答える
0

あなたの質問を理解できたかどうかはわかりませんが、OR 演算子の繰り返しを避けたい場合は、IN('x','y','z') の使用を検討してください - 可能な値をリストします。これは、[何か] = 'x' OR [何か] = 'y' OR [何か] = 'z' よりも読みやすいでしょう。

于 2013-10-02T09:51:47.643 に答える