Sql存储过程的参数为大批量的字符串的问题

时间:2021-08-26 09:03:02
Sql存储过程的问题:
当存储过程参数为大批量的字符串,并且这字符串中的值不是一个字段值的累加,而是两个或者以上字段值的累加,这种情况下怎么做最好。
具体如下:
Create  procedure myproc
(
AA Varchar(4)
,BB Varchar(4)
,CC Varchar(4)
)
As
--仅仅是个例子,实际的执行语句比这要复杂,耗时
select
 *
from 
mytb
where 
tbA=AA
and
tbB=BB
and
tbC=CC
传的参数为
'11','11','11'
'22','33','44'
'13','14','15'
'33','34','56'
'14','34','24'
'13','23','34'
 ............
 ............
 ............
'56','56','87'
'18','12','15'
'77','23','15'
'15','56','58'

并且这些串加起来会可能超过八千


开发环境是.NET2005+SQL2000
哪位能给个好点的策略,
希望运行时间尽可能的短,当然越简单越好

18 个解决方案

#1


什么样的情况会有传这样的值呢?

#2


你傳入的參數也是一組一組的傳吧
一組不會超過8000吧?

#3


我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了

#4


Create  procedure myproc 

AA Varchar(4) 
,BB Varchar(4) 
,CC Varchar(4) 

As 
---->
Create  procedure myproc 

@AA Varchar(4) 
,@BB Varchar(4) 
,@CC Varchar(4) 

As 

#5


一组一组的传的话,对这些每一组抽出的数据进行综合数学计算就相当麻烦,
还有如果说我要传3000组左右的参数,这样会很慢吧

#6


引用 4 楼 dobear_0922 的回复:
SQL codeCreate  procedure myproc 

AA Varchar(4) 
,BB Varchar(4) 
,CC Varchar(4) 

As 
---->
Create  procedure myproc 

@AA Varchar(4) 
,@BB Varchar(4) 
,@CC Varchar(4) 

As 

呵呵,刚从mySql转过来,习惯还是这样写,错了。。。。。。

#7


引用 3 楼 weilejinbuabcde 的回复:
我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了

为什么不用将页面的值放在dataset里利用数据适配器来做?

#8


引用 7 楼 hyde100 的回复:
引用 3 楼 weilejinbuabcde 的回复:
我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了 
 
为什么不用将页面的值放在dataset里利用数据适配器来做?

数据适配器没用过,不过这个计算过程在数据适配器里面好做么,计算好像是比较麻烦,在存储过程中做这个计算倒是比较容易

#9


SQL 2005参数类型可以是Text,不知道SQL 2000是否可以。

#10


引用 8 楼 weilejinbuabcde 的回复:
引用 7 楼 hyde100 的回复:
引用 3 楼 weilejinbuabcde 的回复: 
我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了 

为什么不用将页面的值放在dataset里利用数据适配器来做? 
 
数据适配器没用过,不过这个计算过程在数据适配器里面好做么,计算好像是比较麻烦…


数据适配器是跟你写的存储过程相连的,其实就是数据是一条一条传进去的,而不是像你那样全进去,数据适配器是跟存储过程绑定的

#11


引用 10 楼 hyde100 的回复:
引用 8 楼 weilejinbuabcde 的回复:
引用 7 楼 hyde100 的回复: 
引用 3 楼 weilejinbuabcde 的回复: 
我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了 

为什么不用将页面的值放在dataset里利用数据适配器来做? 

数据适配器没用过,不过这个计算过程在数据…

那样不是还是,一条一条逐条取记录么,再进行计算的时候不是还是很罗索么

#12


引用 2 楼 wufeng4552 的回复:
你傳入的參數也是一組一組的傳吧 
一組不會超過8000吧? 

传的值就是如果单独传的话就是三个值,放在一起穿就是n个三个值

#13


呵呵,因为没看到你具体的计算操作,所以这里只是讨论方式而已~

#14


引用 13 楼 hyde100 的回复:
呵呵,因为没看到你具体的计算操作,所以这里只是讨论方式而已~

我也想过,如果逐条去取,然后放到c#中的datatable中,再计算,也是可以实现的,
但是要是取得次数太多的话,然后再计算的话,那就慢死了
还是希望在服务器端能处理好,我感觉更好一些,不过都比较不理想,还是想找个更好的方法。

#15


给你这样一个思路参考一下:将所有的参数传到数据库中(可以用文件传,也可以用字符串传)形成一个临时表(这里要以你的判断条件作为一条记录),让后通过系统表syscolumns来拼接成查询语句查询。
要判断的数据表:
create table #tb(
id int identity(1,1),
value1 varchar(5),
value2 varchar(5),
value3 varchar(5))
insert into #tb
select 'aa','bb','cc' union
select 'dd','ee','ff' union
select 'gg','hh','ii'

参数临时表:
create table #tb1(
id int identity(1,1),
value1 varchar(5),
value2 varchar(5),
value3 varchar(5))
insert into #tb1
select 'aa','bb','cc' union
select 'dd','dd','ff' union
select 'gg','hh','ii'

通过系统表拼成select语句where条件
declare @where varchar(500)
set @where = ''
select @where = @where +' and t0.'+name +'=t1.' + name from syscolumns
where id = object_id('#tb')
set @where = stuff(@where,1,4,'')

执行结果:
exec('select t0.* from #tb1 t0,#tb t1 where ' + @where )

不知这样能否实习您的需求?

#16


SQL 2005参数类型可以是Text,不知道SQL 2000是否可以。

#17


这样的话用2005可以。

#18


例子:例如每组有五个参数,这五个参数之间用“|”隔开,然后组与组之间用“#”隔开,如下
#|QMS1915||1||2007/08/02||1||825C2020|#
#|QMT5042||3||2007/08/02||2||825VN047|#
组成字符串
“#|QMS1915||1||2007/08/02||1||825C2020|##|QMT5042||3||2007/08/02||2||825VN047|#”
组数多了雷同
存储过程的参数设置为text类型

Create proc myproc(
 @Mstr  Text
)
然后传参数给该存储过程
select 
AA,
BB,
CC,
DD,
EE
from
mytb
where
CHARINDEX('#|'+AA+'||'+'BB'+'||'+CC+'||'+DD+'||'+EE+'|#',@Mstr)>0
这样就可以了,如果你的字符串真的要超过text那么就没治了,
参考如下:

ntext、text   和   image   
  用于存储大型非   Unicode   字符、Unicode   字符及二进制数据的固定长度和可变长度数据类型。Unicode   数据使用   UNICODE   UCS-2   字符集。   
    
  ntext   
    
  可变长度   Unicode   数据的最大长度为   230   -   1   (1,073,741,823)   个字符。存储大小是所输入字符个数的两倍(以字节为单位)。ntext   在   SQL-92   中的同义词是   national   text。   
    
  text   
    
  服务器代码页中的可变长度非   Unicode   数据的最大长度为   231-1   (2,147,483,647)   个字符。当服务器代码页使用双字节字符时,存储量仍是   2,147,483,647   字节。存储大小可能小于   2,147,483,647   字节(取决于字符串)。   
    
  image   
    
  可变长度二进制数据介于   0   与   231-1   (2,147,483,647)   字节之间。     

#1


什么样的情况会有传这样的值呢?

#2


你傳入的參數也是一組一組的傳吧
一組不會超過8000吧?

#3


我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了

#4


Create  procedure myproc 

AA Varchar(4) 
,BB Varchar(4) 
,CC Varchar(4) 

As 
---->
Create  procedure myproc 

@AA Varchar(4) 
,@BB Varchar(4) 
,@CC Varchar(4) 

As 

#5


一组一组的传的话,对这些每一组抽出的数据进行综合数学计算就相当麻烦,
还有如果说我要传3000组左右的参数,这样会很慢吧

#6


引用 4 楼 dobear_0922 的回复:
SQL codeCreate  procedure myproc 

AA Varchar(4) 
,BB Varchar(4) 
,CC Varchar(4) 

As 
---->
Create  procedure myproc 

@AA Varchar(4) 
,@BB Varchar(4) 
,@CC Varchar(4) 

As 

呵呵,刚从mySql转过来,习惯还是这样写,错了。。。。。。

#7


引用 3 楼 weilejinbuabcde 的回复:
我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了

为什么不用将页面的值放在dataset里利用数据适配器来做?

#8


引用 7 楼 hyde100 的回复:
引用 3 楼 weilejinbuabcde 的回复:
我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了 
 
为什么不用将页面的值放在dataset里利用数据适配器来做?

数据适配器没用过,不过这个计算过程在数据适配器里面好做么,计算好像是比较麻烦,在存储过程中做这个计算倒是比较容易

#9


SQL 2005参数类型可以是Text,不知道SQL 2000是否可以。

#10


引用 8 楼 weilejinbuabcde 的回复:
引用 7 楼 hyde100 的回复:
引用 3 楼 weilejinbuabcde 的回复: 
我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了 

为什么不用将页面的值放在dataset里利用数据适配器来做? 
 
数据适配器没用过,不过这个计算过程在数据适配器里面好做么,计算好像是比较麻烦…


数据适配器是跟你写的存储过程相连的,其实就是数据是一条一条传进去的,而不是像你那样全进去,数据适配器是跟存储过程绑定的

#11


引用 10 楼 hyde100 的回复:
引用 8 楼 weilejinbuabcde 的回复:
引用 7 楼 hyde100 的回复: 
引用 3 楼 weilejinbuabcde 的回复: 
我做的一个页面,需要从页面中的一个GridView中取出每一行的前三个字段,然后依次根据每一行的值去到几个数据表中取数据,(中间还有一些数学计算不说了),最后然后对一个计算过生成的字段做处理,所以这样传了 

为什么不用将页面的值放在dataset里利用数据适配器来做? 

数据适配器没用过,不过这个计算过程在数据…

那样不是还是,一条一条逐条取记录么,再进行计算的时候不是还是很罗索么

#12


引用 2 楼 wufeng4552 的回复:
你傳入的參數也是一組一組的傳吧 
一組不會超過8000吧? 

传的值就是如果单独传的话就是三个值,放在一起穿就是n个三个值

#13


呵呵,因为没看到你具体的计算操作,所以这里只是讨论方式而已~

#14


引用 13 楼 hyde100 的回复:
呵呵,因为没看到你具体的计算操作,所以这里只是讨论方式而已~

我也想过,如果逐条去取,然后放到c#中的datatable中,再计算,也是可以实现的,
但是要是取得次数太多的话,然后再计算的话,那就慢死了
还是希望在服务器端能处理好,我感觉更好一些,不过都比较不理想,还是想找个更好的方法。

#15


给你这样一个思路参考一下:将所有的参数传到数据库中(可以用文件传,也可以用字符串传)形成一个临时表(这里要以你的判断条件作为一条记录),让后通过系统表syscolumns来拼接成查询语句查询。
要判断的数据表:
create table #tb(
id int identity(1,1),
value1 varchar(5),
value2 varchar(5),
value3 varchar(5))
insert into #tb
select 'aa','bb','cc' union
select 'dd','ee','ff' union
select 'gg','hh','ii'

参数临时表:
create table #tb1(
id int identity(1,1),
value1 varchar(5),
value2 varchar(5),
value3 varchar(5))
insert into #tb1
select 'aa','bb','cc' union
select 'dd','dd','ff' union
select 'gg','hh','ii'

通过系统表拼成select语句where条件
declare @where varchar(500)
set @where = ''
select @where = @where +' and t0.'+name +'=t1.' + name from syscolumns
where id = object_id('#tb')
set @where = stuff(@where,1,4,'')

执行结果:
exec('select t0.* from #tb1 t0,#tb t1 where ' + @where )

不知这样能否实习您的需求?

#16


SQL 2005参数类型可以是Text,不知道SQL 2000是否可以。

#17


这样的话用2005可以。

#18


例子:例如每组有五个参数,这五个参数之间用“|”隔开,然后组与组之间用“#”隔开,如下
#|QMS1915||1||2007/08/02||1||825C2020|#
#|QMT5042||3||2007/08/02||2||825VN047|#
组成字符串
“#|QMS1915||1||2007/08/02||1||825C2020|##|QMT5042||3||2007/08/02||2||825VN047|#”
组数多了雷同
存储过程的参数设置为text类型

Create proc myproc(
 @Mstr  Text
)
然后传参数给该存储过程
select 
AA,
BB,
CC,
DD,
EE
from
mytb
where
CHARINDEX('#|'+AA+'||'+'BB'+'||'+CC+'||'+DD+'||'+EE+'|#',@Mstr)>0
这样就可以了,如果你的字符串真的要超过text那么就没治了,
参考如下:

ntext、text   和   image   
  用于存储大型非   Unicode   字符、Unicode   字符及二进制数据的固定长度和可变长度数据类型。Unicode   数据使用   UNICODE   UCS-2   字符集。   
    
  ntext   
    
  可变长度   Unicode   数据的最大长度为   230   -   1   (1,073,741,823)   个字符。存储大小是所输入字符个数的两倍(以字节为单位)。ntext   在   SQL-92   中的同义词是   national   text。   
    
  text   
    
  服务器代码页中的可变长度非   Unicode   数据的最大长度为   231-1   (2,147,483,647)   个字符。当服务器代码页使用双字节字符时,存储量仍是   2,147,483,647   字节。存储大小可能小于   2,147,483,647   字节(取决于字符串)。   
    
  image   
    
  可变长度二进制数据介于   0   与   231-1   (2,147,483,647)   字节之间。