2

我有一个存储过程,不知何故

create SP_justest
(@datefrom as smalldatetime,
@dateto as smalldatetime,
@rank as varchar(1),
@Filter as varchar(8000)
)

select * from finhours
where (div_cde = @filter)
and date_from = @datefrom
and date_to = @dateto
and rank = @rank


GO

所以在 vb.net 中,我有一个调用存储过程的子程序,这里是子程序的确切代码:

Private Sub InsertPayRollRecords()
    Try
        'SQLConn.Open()

        sqlcomm.CommandText = "dbo.SP_INSERTVALUESINTOPR"

        sqlcomm.CommandType = CommandType.StoredProcedure

        sqlcomm.Parameters.Add("@DATEFROM", DateValue(dtpCFrom.Value))
        sqlcomm.Parameters.Add("@DATETO", DateValue(dtpCTo.Value))
        sqlcomm.Parameters.Add("@RANK", rank)
        sqlcomm.Parameters.Add("@FILTER", ReturnDivision())

        sqlcomm.Connection = SQLConn
        sqlcomm.CommandTimeout = 999999
        sqlcomm.ExecuteNonQuery()

    Catch ex As Exception
        MsgBox(ex.ToString)
    End Try
End Sub

@filter 的值如下:

'AP0' OR div_cde = 'FO0'  OR div_cde = 'ME0'  OR div_cde = 'SO0'  OR div_cde = 'XO0'

问题是,当我从 VB.net 2000 启动它时,我根本没有遇到任何错误,它只是没有

4

4 回答 4

1

当您发现自己将列表传递给存储过程时,请考虑“表”。您的过程可以引用表或视图:

select * from finhours
where 
and date_from = @datefrom
and date_to = @dateto
and rank = @rank
and div_cde in (select div_cde from interesting_division_codes)

通常该列表不是任意的。相反,他们属于某个群体。然后你结束了

select * from finhours
where 
and date_from = @datefrom
and date_to = @dateto
and rank = @rank
and div_cde in (select div_cde 
                from interesting_division_codes
                where div_category = @div_cat
                )

这是高度优选的。它的处理效率更高,并导致更一致的结果。更不用说它会引发一些关于团体数量及其成员的精彩讨论。

如果 div_cde 值的列表无法在数据库中派生并且是每个进程的,请使用临时表。如果它确实是任意的并且过滤器值仅使用一次,请将它们插入表参数并传递它而不是 varchar,然后在查询中加入它。

于 2013-01-09T07:57:02.213 回答
0

感谢你们的想法,我找到了我的问题的答案。

我必须使用动态 SQL,但由于 sql server 2000 中 nvarchar(4000) 和 varchar(8000) 变量的大小有限,我认为不可能使用 sp_executesql。(如果我在这里错了,请纠正我。)因为 sp_executesql 将使用一个变量,该变量应声明为 nvarchar,其大小为 4000,但我必须触发的查询为 16000+。

(如果您有任何想法在不使用 nvarchar(max) 的情况下在 sp_executesql 上触发它,请告诉我。)

所以我用了这个方法

declare @QueryStart as string
declare @QueryBody as string
declare @Queryfrom as string
declare @querywhere as string

set @QueryStart  = <8000 character statement>
set @QueryBody = <8000 character statement>
set @Queryfrom = <8000 character statement>
set @querywhere = <8000 character statement>


exec (@QueryStart + @QueryBody + @Queryfrom + @querywhere)

由于 sql 注入的可能性,不建议使用此过程,但这是我能想到的在 sql server 2000 中执行此操作的唯一方法。

但如果有人有更有效的答案,请告诉我:D

于 2013-01-21T03:10:49.803 回答
0

好吧,如果您有这样的过滤器,那么您需要在 sql server 中执行动态查询 ..您可以使用sp_executesqlsql server 的程序来完成

DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
DECLARE  datefrom1 smalldatetime;
DECLARE  @dateto1 smalldatetime;
DECLARE  @rank1 varchar(1);
DECLARE  @Filter1 varchar(8000);

/* Build the SQL string one time.*/
SET @SQLString =
     N'select * from finhours
       where (div_cde = @filter)
      and date_from = @datefrom
      and date_to = @dateto
      and rank = @rank';

SET @ParmDefinition = N'@datefrom1 as smalldatetime,
                         @dateto1 as smalldatetime,
                        @rank1 as varchar(1),
                        @Filter1 as varchar(8000)';


/* Execute the string with the first parameter value. */

EXECUTE sp_executesql @SQLString, @ParmDefinition,
                      @datefrom1 =@datefrom,
                      @dateto1 =@dateto,
                      @rank1 = @rank,
                      @Filter1 = @Filter;
于 2013-01-08T06:59:35.810 回答
0

@filter不能像书面的那样工作。 where (div_cde = @filter)期望来自过滤器的简单值。

于 2013-01-08T07:00:14.553 回答