帮你改一个地方: 表名变量不要传递,只能连接字符串生成 1. set @SQLString=N'insert #t select vID from '+@Table +'where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth' set @ParmDefinition=N'@Table varchar(20)' exec sp_executesql @SQLString,@ParmDefinition,@Table ---->>>>>> set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth='+@iDepth exec(@SQLString)2. set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from @Table)' set @ParmDefinition=N'@Table varchar(20)' exec sp_executesql @SQLString,@ParmDefinition,@Table -------> set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+')' exec sp_executesql @SQLString,N'@vTempID varchar(20) output ', @vTempID output
create table CustomerClass( vID varchar(30) constraint pkCustomerClass primary key , vCustomerClassName varchar(40) NOT NULL, vRes varchar(80), vParentID varchar(30) NULL, iDepth Int NULL ) go --存储过程为 CREATE procedure prcIDAutoGen @vSourceID varchar(30),@cIsSubNode char(1),@Table varchar(20), @vIncrement varchar(30) output as /*本存储过程使用*/ declare @iDepth int declare @iLen int declare @vTempID varchar(30) /*sp_executesql使用*/ declare @SQLString nvarchar(500) declare @ParmDefinition nvarchar(50) /*新建一个临时表*/ select @vSourceID as vID,@iDepth as iDepth into #t /*当添加类型为子结点时*/ if @cIsSubNode='y' begin /*查询是否有原记录*/ set @SQLString=N'select vID from '+@Table +'where vID = '''+ltrim(rtrim(@vSourceID))+'''' set @ParmDefinition=N'@Table varchar(20)' exec sp_executesql @SQLString,@ParmDefinition,@Table /*如果存在原记录,则查询此记录的下一级所有子记录*/ if @@rowcount > 0 begin set @iDepth=@iDepth+1 set @SQLString=N'insert #t select vID from '+@Table +'where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth' set @ParmDefinition=N'@Table varchar(20)' exec sp_executesql @SQLString,@ParmDefinition,@Table end /*得到子记录的最大编号*/ select @vTempID =isnull(max(vID),'0') from #t /*返回新的最大编号*/ set @iLen=@iLen*3 select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(38,0))+1) as varchar),@iLen) end /*当添加的类型为兄弟结点时*/ else begin /*查询是否有原记录*/ set @SQLString=N'select vID from '+@Table +'where vID = '''+ltrim(rtrim(@vSourceID))+'''' set @ParmDefinition=N'@Table varchar(20)' exec sp_executesql @SQLString,@ParmDefinition,@Table /*如果存在原记录,则查询此记录的同一级所有记录*/ if @@rowcount > 0 begin set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from @Table)' set @ParmDefinition=N'@Table varchar(20)' exec sp_executesql @SQLString,@ParmDefinition,@Table end /*得到子记录的最大编号*/ select @vTempID =isnull(max(vID),'0') from #t /*返回新的最大编号*/ set @iLen=len(ltrim(rtrim(@vSourceID))) select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(38,0))+1)as varchar),@iLen) end
两个地方,同样修改:select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(@iLen,0))+1))as varchar(@iLen)),@iLen)-> select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(38,0))+1) as varchar),@iLen)
varchar如果没有在数据定义或变量声明语句中指定 n,则默认长度为 1。如果没有使用 CAST 函数指定 n,则默认长度为 30。 decimal最大精度为38 sp_executesql 执行可以多次重用或动态生成的 Transact-SQL 语句或批处理。Transact-SQL 语句或批处理可以包含嵌入参数。语法 sp_executesql [@stmt =] stmt [ {, [@params =] N'@parameter_name data_type [,...n]' } {, [@param1 =] 'value1' [,...n] } ]参数 [@stmt =] stmt包含 Transact-SQL 语句或批处理的 Unicode 字符串,stmt 必须是可以隐式转换为 ntext 的 Unicode 常量或变量。不允许使用更复杂的 Unicode 表达式(例如使用 + 运算符串联两个字符串)。不允许使用字符常量。如果指定常量,则必须使用 N 作为前缀。例如,Unicode 常量 N'sp_who' 是有效的,但是字符常量 'sp_who' 则无效。字符串的大小仅受可用数据库服务器内存限制。stmt 可以包含与变量名形式相同的参数,例如:N'SELECT * FROM Employees WHERE EmployeeID = @IDParameter'stmt 中包含的每个参数在 @params 参数定义列表和参数值列表中均必须有对应项。[@params =] N'@parameter_name data_type [,...n]'字符串,其中包含已嵌入到 stmt 中的所有参数的定义。该字符串必须是可以隐式转换为 ntext 的 Unicode 常量或变量。每个参数定义均由参数名和数据类型组成。n 是表明附加参数定义的占位符。stmt 中指定的每个参数都必须在 @params 中定义。如果 stmt 中的 Transact-SQL 语句或批处理不包含参数,则不需要 @params。该参数的默认值为 NULL。[@param1 =] 'value1'参数字符串中定义的第一个参数的值。该值可以是常量或变量。必须为 stmt 中包含的每个参数提供参数值。如果 stmt 中包含的 Transact-SQL 语句或批处理没有参数,则不需要值。n附加参数的值的占位符。这些值只能是常量或变量,而不能是更复杂的表达式,例如函数或使用运算符生成的表达式。返回代码值 0(成功)或 1(失败)结果集 从生成 SQL 字符串的所有 SQL 语句返回结果集。注释 在批处理、名称作用域和数据库上下文方面,sp_executesql 与 EXECUTE 的行为相同。sp_executesql stmt 参数中的 Transact-SQL 语句或批处理在执行 sp_executesql 语句时才编译。然后编译 stmt 中的内容并作为执行计划运行(独立于名为 sp_executesql 的批处理的执行计划)。sp_executesql 批处理不能引用调用 sp_executesql 的批处理中声明的变量。sp_executesql 批处理中的本地游标和变量对调用 sp_executesql 的批处理是不可见的。对数据库上下文所作的更改只在 sp_executesql 语句结束前有效。如果只更改了语句中的参数值,则 sp_executesql 可用来代替存储过程多次执行 Transact-SQL 语句。因为 Transact-SQL 语句本身保持不变仅参数值变化,所以 Microsoft® SQL Server™ 查询优化器可能重复使用首次执行时所生成的执行计划。说明 如果语句字符串中的对象名不是全限定名,则该执行计划不会被重用。 sp_executesql 支持与 Transact-SQL 字符串相独立的参数值的设置:DECLARE @IntVariable INT DECLARE @SQLString NVARCHAR(500) DECLARE @ParmDefinition NVARCHAR(500)/* Build the SQL string once.*/ SET @SQLString = N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = @level' SET @ParmDefinition = N'@level tinyint' /* Execute the string with the first parameter value. */ SET @IntVariable = 35 EXECUTE sp_executesql @SQLString, @ParmDefinition, @level = @IntVariable /* Execute the same string with the second parameter value. */ SET @IntVariable = 32 EXECUTE sp_executesql @SQLString, @ParmDefinition, @level = @IntVariable替换 sp_executesql 中的参数的能力,与使用 EXECUTE 语句执行字符串相比,有下列优点: 因为在 sp_executesql 中,Transact-SQL 语句的实际文本在两次执行之间未改变,所以查询优化器应该能将第二次执行中的 Transact-SQL 语句与第一次执行时生成的执行计划匹配。这样,SQL Server 不必编译第二条语句。 Transact-SQL 字符串只生成一次。 整型参数按其本身格式指定。不需要转换为 Unicode。 权限 执行权限默认授予 public 角色。示例 A. 执行简单的 SELECT 语句 下面的示例创建并执行一个简单的 SELECT 语句,其中包含名为 @level 的嵌入参数。execute sp_executesql N'select * from pubs.dbo.employee where job_lvl = @level', N'@level tinyint', @level = 35B. 执行动态生成的字符串 下面的示例显示使用 sp_executesql 执行动态生成的字符串。该示例中的存储过程用来向一组表中插入数据,该表用于划分一年的销售数据。一年中的每个月均有一个表,格式如下:CREATE TABLE May1998Sales (OrderID INT PRIMARY KEY, CustomerID INT NOT NULL, OrderDate DATETIME NULL CHECK (DATEPART(yy, OrderDate) = 1998), OrderMonth INT CHECK (OrderMonth = 5), DeliveryDate DATETIME NULL, CHECK (DATEPART(mm, OrderDate) = OrderMonth) )有关从这些分区表中检索数据的更多信息,请参见使用包含分区数据的视图。 每个表的名称由月份名的前三个字母、年度的四位数字和常量 Sales 组成。名称可以从订单日期动态生成:/* Get the first three characters of the month name. */ SUBSTRING( DATENAME(mm, @PrmOrderDate), 1, 3) + /* Concatenate the four-digit year; cast as character. */ CAST(DATEPART(yy, @PrmOrderDate) AS CHAR(4) ) + /* Concatenate the constant 'Sales'. */ 'Sales'下面示例中的存储过程动态生成并执行一个 INSERT 语句,向适当的表中插入新订单。该存储过程使用订单日期生成应包含数据的表的名称,然后将名称并入 INSERT 语句。(这是 sp_executesql 的一个简单示例。不包含错误检查,也不包括业务规则检查,例如确保两个表之间订单号没有重复。)CREATE PROCEDURE InsertSales @PrmOrderID INT, @PrmCustomerID INT, @PrmOrderDate DATETIME, @PrmDeliveryDate DATETIME AS DECLARE @InsertString NVARCHAR(500) DECLARE @OrderMonth INT-- Build the INSERT statement. SET @InsertString = 'INSERT INTO ' + /* Build the name of the table. */ SUBSTRING( DATENAME(mm, @PrmOrderDate), 1, 3) + CAST(DATEPART(yy, @PrmOrderDate) AS CHAR(4) ) + 'Sales' + /* Build a VALUES clause. */ ' VALUES (@InsOrderID, @InsCustID, @InsOrdDate,' + ' @InsOrdMonth, @InsDelDate)'/* Set the value to use for the order month because functions are not allowed in the sp_executesql parameter list. */ SET @OrderMonth = DATEPART(mm, @PrmOrderDate)EXEC sp_executesql @InsertString, N'@InsOrderID INT, @InsCustID INT, @InsOrdDate DATETIME, @InsOrdMonth INT, @InsDelDate DATETIME', @PrmOrderID, @PrmCustomerID, @PrmOrderDate, @OrderMonth, @PrmDeliveryDateGO在该过程中使用 sp_executesql 比使用 EXECUTE 执行字符串更有效。使用 sp_executesql 时,只生成 12 个版本的 INSERT 字符串,每个月的表 1 个。使用 EXECUTE 时,因为参数值不同,每个 INSERT 字符串均是唯一的。尽管两种方法生成的批处理数相同,但因为 sp_executesql 生成的 INSERT 字符串相似,所以查询优化程序更有可能反复使用执行计划。
想请问前辈 //////////////////////////////////////////////////////////////////////////// 帮你改一个地方: 表名变量不要传递,只能连接字符串生成 1. set @SQLString=N'insert #t select vID from '+@Table +'where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth' set @ParmDefinition=N'@Table varchar(20)' exec sp_executesql @SQLString,@ParmDefinition,@Table ---->>>>>> set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth='+@iDepth exec(@SQLString) ///////////////////////////////////////////////////////////////////////////// 是不是两种方法都可以呀,还是只能exec(@SQLString)?////////////////////////////////////////////////////////////////////////// 2. set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from @Table)' set @ParmDefinition=N'@Table varchar(20)' exec sp_executesql @SQLString,@ParmDefinition,@Table -------> set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+')' exec sp_executesql @SQLString,N'@vTempID varchar(20) output ', @vTempID output第二个是因为你有@vTempID变量要传出,所以用 sp_executesql N'@vTempID varchar(20) output '是SP_executesql内部量.用来OUTPUT结果. @vTempID output 你存储过程的变量用来接收传出 ///////////////////////////////////////////////////////////////////////// 我若是这样做exec sp_executesql @SQLString,@ParmDefinition,@Table 难道就输不出了,也就是传递不出去了吗?我看看了SQL 2000的联机帮助,我更加迷惑了。还有呀,联机帮助里面好像对每个变量都用参数传递的,为何我的存储过程有的传,有的不传,到底怎么一个规则呀
你还没理解sp_executesql 1.sp_executesql当你要用到传出参数时,用它。当然也可以用传入参数。 但表名当变量不能象你那样传。2 执行sp_executesql,就相当于你在存储过程中执行另一个存储过程。另一个存储过程 的变量也要定义。如: declare @c int,@sql nvarchar(4000) set @sql='select @i=@a+@b' exec sp_executesql @sql,N'@i int output,@a int,@b int',@a=3,@b=4,@i=@c output select @c上面的:@i int output,@a int,@b int是内部的变量。@C是外部的变量上面的代码相当于,以下过程:create proc proc1(@i int output,@a int,@b int) as set @i=@a+@b godeclare @c int exec proc1 @i=@c output,@a=3,@b=4 select @c
EXEC(语句) 跟SP_EXECUTESQL没有多大区别。 唯一区别是,SP_EXECUTESQL可以传入传出参数,另一个EXEC不行。你第一个: set @SQLString=N'insert #t select vID from 只是表插入记录,所以合成动态SQL后,直接EXEC()就行了,当然用SP_EXECUTESQL也行。而第二个: set @SQLString=N'select @vTempID =isnull(max(vID),'..... @vTempID要当执行结果传回来,只能用SP_EXECUTESQL。
哈哈,不客气, 反正我现在没什么事。我看你发300分差不多错误的贴,还有一点一并跟你讲讲:set @SQLString=N'insert #t select vID from '+.....+'.....' 这种相加,就相当于前台的ADOstring.ADD ...... 不论如何,要使合成的SQL语句要能执行。你在查询分析器,程序调试时,在下面加个print,如: set @SQLString=N'insert #t select vID from '+.....+'.....' print @SQLString 再把结果粘贴出来执行,一股你就知道SQL字符串合并过程中错在那儿。只要掌握以上我说的三点。你就可以灵活轻松的应用EXEC 和SP_EXECUTESQL了。
CREATE procedure prcIDAutoGen @vSourceID varchar(30), @iDepth int, @iIsSubNode int, @Table varchar(20), @vIncrement varchar(30) output as begin /*本存储过程使用*/ declare @iLen int declare @vTempID varchar(30) /*sp_executesql使用*/ declare @SQLString nvarchar(500) /*当添加类型为子结点时*/ if @iIsSubNode =1 begin /*深度+1*/ set @iDepth=@iDepth+1 /*新建一个临时表*/ select @vSourceID as vID into #t print 'step 1' /*查询是否有原记录*/ set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+'''' exec(@SQLString) print 'step 2' /*如果存在原记录,则查询此记录的下一级所有子记录*/ if @@rowcount > 0 begin set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth' exec sp_executesql @SQLString,N'@iDepth int',@iDepth print 'step 3' end /*得到子记录的最大编号*/ set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from #t' exec sp_executesql @SQLString,N'@vTempID varchar(30) output',@vTempID output print 'step 4' /*计算得到新的节点长度*/ set @iLen=@iDepth*3 /*返回新的最大编号*/ select @vIncrement=right(cast((cast(substring(@vTempID,1,@iLen) as decimal(3,0))+1)as varchar),@iLen) print 'step 5' end else begin /*查询是否有原记录*/ set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+'''' exec(@SQLString) /*如果存在原记录,则查询此记录的同一级所有记录*/ print 'test 1' if @@rowcount > 0 begin set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+' where iDepth='+@iDepth+')' exec sp_executesql @SQLString,N'@vTempID varchar(30) output',@vTempID output print 'test 2' end /*返回新的最大编号*/ set @iLen=len(ltrim(rtrim(@vSourceID))) select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen) print 'test 3' end end现在的问题如下: 1、用以下代码测试 declare @c varchar(30) exec prcIDAutoGen " ",0,1,"customerclass",@vIncrement=@c output select @c 得到错误信息 (所影响的行数为 1 行) step 1 (所影响的行数为 0 行) step 2 step 4 服务器: 消息 8114,级别 16,状态 5,过程 prcIDAutoGen,行 40 将数据类型 varchar 转换为 numeric 时出错。2用以下代码测试 declare @c varchar(30) exec prcIDAutoGen " ",0,0,"customerclass",@vIncrement=@c output select @c 输出结果为NULL我联机帮助看了半天,却仍不知是为什么?向高手请教,再次感谢
CREATE procedure prcIDAutoGen @vSourceID varchar(30), @iDepth int, @iIsSubNode int, @Table varchar(20), @vIncrement varchar(30) output as begin declare @iLen int declare @vTempID varchar(30) declare @SQLString nvarchar(500) if @iIsSubNode =1 begin set @iDepth=@iDepth+1 set @iLen=@iDepth*3 set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+'''' exec(@SQLString) if @@rowcount > 0 begin select @vSourceID as vID into #t set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth' exec sp_executesql @SQLString,N'@iDepth int',@iDepth if @@rowcount > 0 begin set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from #t' exec sp_executesql @SQLString,N'@vTempID varchar(30) output',@vTempID output set @SQLString='select @vIncrement=right(''000''+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen)' exec sp_executesql @SQLString,N'@vIncrement varchar(30) output,@vTempID varchar(30),@iLen int',@vIncrement out,@vTempID,@iLen end else begin select @vIncrement=ltrim(rtrim(@vSourceID))+'001' end end else begin select @vIncrement='001' end end else begin set @iLen=len(ltrim(rtrim(@vSourceID))) set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+'''' exec(@SQLString) if @@rowcount > 0 begin set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+' where iDepth=@iDepth)' exec sp_executesql @SQLString,N'@vTempID varchar(30) output,@iDepth int',@vTempID output,@iDepth set @SQLString='select @vIncrement=right(''000''+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen)' exec sp_executesql @SQLString,N'@vIncrement varchar(30) output,@vTempID varchar(30),@iLen int',@vIncrement out,@vTempID,@iLen end else begin select @vIncrement='001' end end end这段代码已经完整实现了,经过多次测试,确保无误
关键技术说明 1、set @SQLString='select @vIncrement=right(''000''+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen)' exec sp_executesql @SQLString,N'@vIncrement varchar(30) output,@vTempID varchar(30),@iLen int',@vIncrement out,@vTempID,@iLen2、'+cast(@iLen as varchar)+')'3、'@iLen+')'方法1、2正确,3错误,建议使用第1种
/*--共计6处错误,按下面的修改后,就可以了--*/CREATE procedure prcIDAutoGen @vSourceID varchar(30), @iDepth int, @iIsSubNode int, @Table varchar(20), @vIncrement varchar(30) output as begin /*本存储过程使用*/ declare @iLen int declare @vTempID varchar(30) /*sp_executesql使用*/ declare @SQLString nvarchar(500) /*当添加类型为子结点时*/ if @iIsSubNode =1 begin /*深度+1*/ set @iDepth=@iDepth+1 /*新建一个临时表*/ select @vSourceID as vID into #t print 'step 1' /*查询是否有原记录*/ set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+'''' exec(@SQLString) --** 错误1:print 语句会影响@@rowcount的值,所以要去掉 -- print 'step 2' --*********这个会影响@@rowcount的值,要去掉才能得到正确结果 /*如果存在原记录,则查询此记录的下一级所有子记录*/ if @@rowcount > 0 begin set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth' exec sp_executesql @SQLString,N'@iDepth int',@iDepth print 'step 3' end /*得到子记录的最大编号*/ set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from #t' exec sp_executesql @SQLString,N'@vTempID varchar(30) output',@vTempID output print 'step 4' /*计算得到新的节点长度*/ set @iLen=@iDepth*3 /*返回新的最大编号*/--** 错误2:如果表中无数据,且@vSourceID为空,则@vTempID也为空,这时要单独处理,否则出错 if ltrim(@vTempID)='' set @vIncrement=@vTempID else begin --** 错误3:decimal()中不能用变量 -- select @vIncrement=right(cast((cast(substring(@vTempID,1,@iLen) as decimal(3,0))+1)as varchar),@iLen) set @SQLString='select @vIncrement=right(cast((cast(substring(@vTempID,1,'+cast(@iLen as varchar)+') as decimal(3,0))+1)as varchar),'+cast(@iLen as varchar)+')' exec sp_executesql @SQLString ,N'@vIncrement varchar(30) output,@vTempID varchar(30)' ,@vIncrement out,@vTempID print 'step 5' end end else begin /*查询是否有原记录*/ set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+'''' exec(@SQLString) /*如果存在原记录,则查询此记录的同一级所有记录*/--** 错误4:print 语句会影响@@rowcount的值,所以要去掉 -- print 'test 1' if @@rowcount > 0 begin --** 错误5:未进行数据类型转换 -- set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+' where iDepth='+@iDepth+')' set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+' where iDepth=@iDepth)' exec sp_executesql @SQLString,N'@vTempID varchar(30) output,@iDepth int',@vTempID output,@iDepth print 'test 2' end /*返回新的最大编号*/ set @iLen=len(ltrim(rtrim(@vSourceID)))--** 错误6:decimal()中不能用变量 -- select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen) set @SQLString='select @vIncrement=right(''000''+cast((cast(substring(@vTempID,1,'+cast(@iLen as varchar)+') as decimal(30,0))+1)as varchar),'+cast(@iLen as varchar)+')' exec sp_executesql @SQLString ,N'@vIncrement varchar(30) output,@vTempID varchar(30)' ,@vIncrement out,@vTempID print 'test 3' end end go
表名变量不要传递,只能连接字符串生成
1.
set @SQLString=N'insert #t select vID from '+@Table +'where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth'
set @ParmDefinition=N'@Table varchar(20)'
exec sp_executesql @SQLString,@ParmDefinition,@Table
---->>>>>>
set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth='+@iDepth
exec(@SQLString)2.
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from @Table)'
set @ParmDefinition=N'@Table varchar(20)'
exec sp_executesql @SQLString,@ParmDefinition,@Table
------->
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+')'
exec sp_executesql @SQLString,N'@vTempID varchar(20) output ', @vTempID output
vID varchar(30) constraint pkCustomerClass primary key ,
vCustomerClassName varchar(40) NOT NULL,
vRes varchar(80),
vParentID varchar(30) NULL,
iDepth Int NULL
)
go
--存储过程为
CREATE procedure prcIDAutoGen @vSourceID varchar(30),@cIsSubNode char(1),@Table varchar(20), @vIncrement varchar(30) output
as
/*本存储过程使用*/
declare @iDepth int
declare @iLen int
declare @vTempID varchar(30)
/*sp_executesql使用*/
declare @SQLString nvarchar(500)
declare @ParmDefinition nvarchar(50)
/*新建一个临时表*/
select @vSourceID as vID,@iDepth as iDepth into #t
/*当添加类型为子结点时*/
if @cIsSubNode='y'
begin
/*查询是否有原记录*/
set @SQLString=N'select vID from '+@Table +'where vID = '''+ltrim(rtrim(@vSourceID))+''''
set @ParmDefinition=N'@Table varchar(20)'
exec sp_executesql @SQLString,@ParmDefinition,@Table
/*如果存在原记录,则查询此记录的下一级所有子记录*/
if @@rowcount > 0
begin
set @iDepth=@iDepth+1
set @SQLString=N'insert #t select vID from '+@Table +'where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth'
set @ParmDefinition=N'@Table varchar(20)'
exec sp_executesql @SQLString,@ParmDefinition,@Table
end
/*得到子记录的最大编号*/
select @vTempID =isnull(max(vID),'0') from #t
/*返回新的最大编号*/
set @iLen=@iLen*3
select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(38,0))+1) as varchar),@iLen)
end
/*当添加的类型为兄弟结点时*/
else
begin
/*查询是否有原记录*/
set @SQLString=N'select vID from '+@Table +'where vID = '''+ltrim(rtrim(@vSourceID))+''''
set @ParmDefinition=N'@Table varchar(20)'
exec sp_executesql @SQLString,@ParmDefinition,@Table
/*如果存在原记录,则查询此记录的同一级所有记录*/
if @@rowcount > 0
begin
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from @Table)'
set @ParmDefinition=N'@Table varchar(20)'
exec sp_executesql @SQLString,@ParmDefinition,@Table
end
/*得到子记录的最大编号*/
select @vTempID =isnull(max(vID),'0') from #t
/*返回新的最大编号*/
set @iLen=len(ltrim(rtrim(@vSourceID)))
select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(38,0))+1)as varchar),@iLen)
end
decimal最大精度为38
sp_executesql
执行可以多次重用或动态生成的 Transact-SQL 语句或批处理。Transact-SQL 语句或批处理可以包含嵌入参数。语法
sp_executesql [@stmt =] stmt
[
{, [@params =] N'@parameter_name data_type [,...n]' }
{, [@param1 =] 'value1' [,...n] }
]参数
[@stmt =] stmt包含 Transact-SQL 语句或批处理的 Unicode 字符串,stmt 必须是可以隐式转换为 ntext 的 Unicode 常量或变量。不允许使用更复杂的 Unicode 表达式(例如使用 + 运算符串联两个字符串)。不允许使用字符常量。如果指定常量,则必须使用 N 作为前缀。例如,Unicode 常量 N'sp_who' 是有效的,但是字符常量 'sp_who' 则无效。字符串的大小仅受可用数据库服务器内存限制。stmt 可以包含与变量名形式相同的参数,例如:N'SELECT * FROM Employees WHERE EmployeeID = @IDParameter'stmt 中包含的每个参数在 @params 参数定义列表和参数值列表中均必须有对应项。[@params =] N'@parameter_name data_type [,...n]'字符串,其中包含已嵌入到 stmt 中的所有参数的定义。该字符串必须是可以隐式转换为 ntext 的 Unicode 常量或变量。每个参数定义均由参数名和数据类型组成。n 是表明附加参数定义的占位符。stmt 中指定的每个参数都必须在 @params 中定义。如果 stmt 中的 Transact-SQL 语句或批处理不包含参数,则不需要 @params。该参数的默认值为 NULL。[@param1 =] 'value1'参数字符串中定义的第一个参数的值。该值可以是常量或变量。必须为 stmt 中包含的每个参数提供参数值。如果 stmt 中包含的 Transact-SQL 语句或批处理没有参数,则不需要值。n附加参数的值的占位符。这些值只能是常量或变量,而不能是更复杂的表达式,例如函数或使用运算符生成的表达式。返回代码值
0(成功)或 1(失败)结果集
从生成 SQL 字符串的所有 SQL 语句返回结果集。注释
在批处理、名称作用域和数据库上下文方面,sp_executesql 与 EXECUTE 的行为相同。sp_executesql stmt 参数中的 Transact-SQL 语句或批处理在执行 sp_executesql 语句时才编译。然后编译 stmt 中的内容并作为执行计划运行(独立于名为 sp_executesql 的批处理的执行计划)。sp_executesql 批处理不能引用调用 sp_executesql 的批处理中声明的变量。sp_executesql 批处理中的本地游标和变量对调用 sp_executesql 的批处理是不可见的。对数据库上下文所作的更改只在 sp_executesql 语句结束前有效。如果只更改了语句中的参数值,则 sp_executesql 可用来代替存储过程多次执行 Transact-SQL 语句。因为 Transact-SQL 语句本身保持不变仅参数值变化,所以 Microsoft® SQL Server™ 查询优化器可能重复使用首次执行时所生成的执行计划。说明 如果语句字符串中的对象名不是全限定名,则该执行计划不会被重用。
sp_executesql 支持与 Transact-SQL 字符串相独立的参数值的设置:DECLARE @IntVariable INT
DECLARE @SQLString NVARCHAR(500)
DECLARE @ParmDefinition NVARCHAR(500)/* Build the SQL string once.*/
SET @SQLString =
N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = @level'
SET @ParmDefinition = N'@level tinyint'
/* Execute the string with the first parameter value. */
SET @IntVariable = 35
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @IntVariable
/* Execute the same string with the second parameter value. */
SET @IntVariable = 32
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @IntVariable替换 sp_executesql 中的参数的能力,与使用 EXECUTE 语句执行字符串相比,有下列优点: 因为在 sp_executesql 中,Transact-SQL 语句的实际文本在两次执行之间未改变,所以查询优化器应该能将第二次执行中的 Transact-SQL 语句与第一次执行时生成的执行计划匹配。这样,SQL Server 不必编译第二条语句。
Transact-SQL 字符串只生成一次。
整型参数按其本身格式指定。不需要转换为 Unicode。
权限
执行权限默认授予 public 角色。示例
A. 执行简单的 SELECT 语句
下面的示例创建并执行一个简单的 SELECT 语句,其中包含名为 @level 的嵌入参数。execute sp_executesql
N'select * from pubs.dbo.employee where job_lvl = @level',
N'@level tinyint',
@level = 35B. 执行动态生成的字符串
下面的示例显示使用 sp_executesql 执行动态生成的字符串。该示例中的存储过程用来向一组表中插入数据,该表用于划分一年的销售数据。一年中的每个月均有一个表,格式如下:CREATE TABLE May1998Sales
(OrderID INT PRIMARY KEY,
CustomerID INT NOT NULL,
OrderDate DATETIME NULL
CHECK (DATEPART(yy, OrderDate) = 1998),
OrderMonth INT
CHECK (OrderMonth = 5),
DeliveryDate DATETIME NULL,
CHECK (DATEPART(mm, OrderDate) = OrderMonth)
)有关从这些分区表中检索数据的更多信息,请参见使用包含分区数据的视图。 每个表的名称由月份名的前三个字母、年度的四位数字和常量 Sales 组成。名称可以从订单日期动态生成:/* Get the first three characters of the month name. */
SUBSTRING( DATENAME(mm, @PrmOrderDate), 1, 3) +
/* Concatenate the four-digit year; cast as character. */
CAST(DATEPART(yy, @PrmOrderDate) AS CHAR(4) ) +
/* Concatenate the constant 'Sales'. */
'Sales'下面示例中的存储过程动态生成并执行一个 INSERT 语句,向适当的表中插入新订单。该存储过程使用订单日期生成应包含数据的表的名称,然后将名称并入 INSERT 语句。(这是 sp_executesql 的一个简单示例。不包含错误检查,也不包括业务规则检查,例如确保两个表之间订单号没有重复。)CREATE PROCEDURE InsertSales @PrmOrderID INT, @PrmCustomerID INT,
@PrmOrderDate DATETIME, @PrmDeliveryDate DATETIME
AS
DECLARE @InsertString NVARCHAR(500)
DECLARE @OrderMonth INT-- Build the INSERT statement.
SET @InsertString = 'INSERT INTO ' +
/* Build the name of the table. */
SUBSTRING( DATENAME(mm, @PrmOrderDate), 1, 3) +
CAST(DATEPART(yy, @PrmOrderDate) AS CHAR(4) ) +
'Sales' +
/* Build a VALUES clause. */
' VALUES (@InsOrderID, @InsCustID, @InsOrdDate,' +
' @InsOrdMonth, @InsDelDate)'/* Set the value to use for the order month because
functions are not allowed in the sp_executesql parameter
list. */
SET @OrderMonth = DATEPART(mm, @PrmOrderDate)EXEC sp_executesql @InsertString,
N'@InsOrderID INT, @InsCustID INT, @InsOrdDate DATETIME,
@InsOrdMonth INT, @InsDelDate DATETIME',
@PrmOrderID, @PrmCustomerID, @PrmOrderDate,
@OrderMonth, @PrmDeliveryDateGO在该过程中使用 sp_executesql 比使用 EXECUTE 执行字符串更有效。使用 sp_executesql 时,只生成 12 个版本的 INSERT 字符串,每个月的表 1 个。使用 EXECUTE 时,因为参数值不同,每个 INSERT 字符串均是唯一的。尽管两种方法生成的批处理数相同,但因为 sp_executesql 生成的 INSERT 字符串相似,所以查询优化程序更有可能反复使用执行计划。
////////////////////////////////////////////////////////////////////////////
帮你改一个地方:
表名变量不要传递,只能连接字符串生成
1.
set @SQLString=N'insert #t select vID from '+@Table +'where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth'
set @ParmDefinition=N'@Table varchar(20)'
exec sp_executesql @SQLString,@ParmDefinition,@Table
---->>>>>>
set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth='+@iDepth
exec(@SQLString)
/////////////////////////////////////////////////////////////////////////////
是不是两种方法都可以呀,还是只能exec(@SQLString)?//////////////////////////////////////////////////////////////////////////
2.
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from @Table)'
set @ParmDefinition=N'@Table varchar(20)'
exec sp_executesql @SQLString,@ParmDefinition,@Table
------->
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+')'
exec sp_executesql @SQLString,N'@vTempID varchar(20) output ', @vTempID output第二个是因为你有@vTempID变量要传出,所以用 sp_executesql
N'@vTempID varchar(20) output '是SP_executesql内部量.用来OUTPUT结果.
@vTempID output 你存储过程的变量用来接收传出
/////////////////////////////////////////////////////////////////////////
我若是这样做exec sp_executesql @SQLString,@ParmDefinition,@Table
难道就输不出了,也就是传递不出去了吗?我看看了SQL 2000的联机帮助,我更加迷惑了。还有呀,联机帮助里面好像对每个变量都用参数传递的,为何我的存储过程有的传,有的不传,到底怎么一个规则呀
1)如果在SQL语句中两次用到同一个表名变量,那么在参数中是不是要说明两次?
2)另外SQL语句中的每个变量是不是都要在参数列表中说明一下?
1.sp_executesql当你要用到传出参数时,用它。当然也可以用传入参数。
但表名当变量不能象你那样传。2 执行sp_executesql,就相当于你在存储过程中执行另一个存储过程。另一个存储过程
的变量也要定义。如:
declare @c int,@sql nvarchar(4000)
set @sql='select @i=@a+@b'
exec sp_executesql @sql,N'@i int output,@a int,@b int',@a=3,@b=4,@i=@c output
select @c上面的:@i int output,@a int,@b int是内部的变量。@C是外部的变量上面的代码相当于,以下过程:create proc proc1(@i int output,@a int,@b int)
as
set @i=@a+@b
godeclare @c int
exec proc1 @i=@c output,@a=3,@b=4
select @c
唯一区别是,SP_EXECUTESQL可以传入传出参数,另一个EXEC不行。你第一个:
set @SQLString=N'insert #t select vID from
只是表插入记录,所以合成动态SQL后,直接EXEC()就行了,当然用SP_EXECUTESQL也行。而第二个:
set @SQLString=N'select @vTempID =isnull(max(vID),'.....
@vTempID要当执行结果传回来,只能用SP_EXECUTESQL。
反正我现在没什么事。我看你发300分差不多错误的贴,还有一点一并跟你讲讲:set @SQLString=N'insert #t select vID from '+.....+'.....'
这种相加,就相当于前台的ADOstring.ADD ......
不论如何,要使合成的SQL语句要能执行。你在查询分析器,程序调试时,在下面加个print,如:
set @SQLString=N'insert #t select vID from '+.....+'.....'
print @SQLString
再把结果粘贴出来执行,一股你就知道SQL字符串合并过程中错在那儿。只要掌握以上我说的三点。你就可以灵活轻松的应用EXEC 和SP_EXECUTESQL了。
@vSourceID varchar(30),
@iDepth int,
@iIsSubNode int,
@Table varchar(20),
@vIncrement varchar(30) output
as
begin
/*本存储过程使用*/
declare @iLen int
declare @vTempID varchar(30)
/*sp_executesql使用*/
declare @SQLString nvarchar(500)
/*当添加类型为子结点时*/
if @iIsSubNode =1
begin
/*深度+1*/
set @iDepth=@iDepth+1
/*新建一个临时表*/
select @vSourceID as vID into #t
print 'step 1'
/*查询是否有原记录*/
set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+''''
exec(@SQLString)
print 'step 2'
/*如果存在原记录,则查询此记录的下一级所有子记录*/
if @@rowcount > 0
begin
set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth'
exec sp_executesql @SQLString,N'@iDepth int',@iDepth
print 'step 3'
end
/*得到子记录的最大编号*/
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from #t'
exec sp_executesql @SQLString,N'@vTempID varchar(30) output',@vTempID output
print 'step 4'
/*计算得到新的节点长度*/
set @iLen=@iDepth*3
/*返回新的最大编号*/
select @vIncrement=right(cast((cast(substring(@vTempID,1,@iLen) as decimal(3,0))+1)as varchar),@iLen)
print 'step 5'
end
else
begin
/*查询是否有原记录*/
set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+''''
exec(@SQLString)
/*如果存在原记录,则查询此记录的同一级所有记录*/
print 'test 1'
if @@rowcount > 0
begin
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+' where iDepth='+@iDepth+')'
exec sp_executesql @SQLString,N'@vTempID varchar(30) output',@vTempID output
print 'test 2'
end
/*返回新的最大编号*/
set @iLen=len(ltrim(rtrim(@vSourceID)))
select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen)
print 'test 3'
end
end现在的问题如下:
1、用以下代码测试
declare @c varchar(30)
exec prcIDAutoGen " ",0,1,"customerclass",@vIncrement=@c output
select @c
得到错误信息
(所影响的行数为 1 行)
step 1
(所影响的行数为 0 行)
step 2
step 4
服务器: 消息 8114,级别 16,状态 5,过程 prcIDAutoGen,行 40
将数据类型 varchar 转换为 numeric 时出错。2用以下代码测试
declare @c varchar(30)
exec prcIDAutoGen " ",0,0,"customerclass",@vIncrement=@c output
select @c
输出结果为NULL我联机帮助看了半天,却仍不知是为什么?向高手请教,再次感谢
@vSourceID varchar(30),
@iDepth int,
@iIsSubNode int,
@Table varchar(20),
@vIncrement varchar(30) output
as
begin
declare @iLen int
declare @vTempID varchar(30)
declare @SQLString nvarchar(500)
if @iIsSubNode =1
begin
set @iDepth=@iDepth+1
set @iLen=@iDepth*3
set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+''''
exec(@SQLString)
if @@rowcount > 0
begin
select @vSourceID as vID into #t
set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth'
exec sp_executesql @SQLString,N'@iDepth int',@iDepth
if @@rowcount > 0
begin
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from #t'
exec sp_executesql @SQLString,N'@vTempID varchar(30) output',@vTempID output
set @SQLString='select @vIncrement=right(''000''+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen)'
exec sp_executesql @SQLString,N'@vIncrement varchar(30) output,@vTempID varchar(30),@iLen int',@vIncrement out,@vTempID,@iLen
end
else
begin
select @vIncrement=ltrim(rtrim(@vSourceID))+'001'
end
end
else
begin
select @vIncrement='001'
end
end
else
begin
set @iLen=len(ltrim(rtrim(@vSourceID)))
set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+''''
exec(@SQLString)
if @@rowcount > 0
begin
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+' where iDepth=@iDepth)'
exec sp_executesql @SQLString,N'@vTempID varchar(30) output,@iDepth int',@vTempID output,@iDepth
set @SQLString='select @vIncrement=right(''000''+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen)'
exec sp_executesql @SQLString,N'@vIncrement varchar(30) output,@vTempID varchar(30),@iLen int',@vIncrement out,@vTempID,@iLen
end
else
begin
select @vIncrement='001'
end
end
end这段代码已经完整实现了,经过多次测试,确保无误
1、set @SQLString='select @vIncrement=right(''000''+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen)'
exec sp_executesql @SQLString,N'@vIncrement varchar(30) output,@vTempID varchar(30),@iLen int',@vIncrement out,@vTempID,@iLen2、'+cast(@iLen as varchar)+')'3、'@iLen+')'方法1、2正确,3错误,建议使用第1种
@vSourceID varchar(30),
@iDepth int,
@iIsSubNode int,
@Table varchar(20),
@vIncrement varchar(30) output
as
begin
/*本存储过程使用*/
declare @iLen int
declare @vTempID varchar(30)
/*sp_executesql使用*/
declare @SQLString nvarchar(500)
/*当添加类型为子结点时*/
if @iIsSubNode =1
begin
/*深度+1*/
set @iDepth=@iDepth+1
/*新建一个临时表*/
select @vSourceID as vID into #t
print 'step 1'
/*查询是否有原记录*/
set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+''''
exec(@SQLString)
--** 错误1:print 语句会影响@@rowcount的值,所以要去掉
-- print 'step 2' --*********这个会影响@@rowcount的值,要去掉才能得到正确结果 /*如果存在原记录,则查询此记录的下一级所有子记录*/
if @@rowcount > 0
begin
set @SQLString=N'insert #t select vID from '+@Table +' where vParentID in (select vID from #t) and vID not in (select vID from #t) and iDepth=@iDepth'
exec sp_executesql @SQLString,N'@iDepth int',@iDepth
print 'step 3'
end
/*得到子记录的最大编号*/
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from #t'
exec sp_executesql @SQLString,N'@vTempID varchar(30) output',@vTempID output
print 'step 4'
/*计算得到新的节点长度*/
set @iLen=@iDepth*3
/*返回新的最大编号*/--** 错误2:如果表中无数据,且@vSourceID为空,则@vTempID也为空,这时要单独处理,否则出错
if ltrim(@vTempID)=''
set @vIncrement=@vTempID
else
begin
--** 错误3:decimal()中不能用变量
-- select @vIncrement=right(cast((cast(substring(@vTempID,1,@iLen) as decimal(3,0))+1)as varchar),@iLen)
set @SQLString='select @vIncrement=right(cast((cast(substring(@vTempID,1,'+cast(@iLen as varchar)+') as decimal(3,0))+1)as varchar),'+cast(@iLen as varchar)+')'
exec sp_executesql @SQLString
,N'@vIncrement varchar(30) output,@vTempID varchar(30)'
,@vIncrement out,@vTempID
print 'step 5'
end
end
else
begin
/*查询是否有原记录*/
set @SQLString=N'select vID from '+@Table +' where vID = '''+ltrim(rtrim(@vSourceID))+''''
exec(@SQLString)
/*如果存在原记录,则查询此记录的同一级所有记录*/--** 错误4:print 语句会影响@@rowcount的值,所以要去掉
-- print 'test 1'
if @@rowcount > 0
begin
--** 错误5:未进行数据类型转换
-- set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+' where iDepth='+@iDepth+')'
set @SQLString=N'select @vTempID =isnull(max(vID),''0'') from '+@Table+' where vID in (select vID from '+@Table+' where iDepth=@iDepth)'
exec sp_executesql @SQLString,N'@vTempID varchar(30) output,@iDepth int',@vTempID output,@iDepth
print 'test 2'
end
/*返回新的最大编号*/
set @iLen=len(ltrim(rtrim(@vSourceID)))--** 错误6:decimal()中不能用变量
-- select @vIncrement=right('000'+cast((cast(substring(@vTempID,1,@iLen) as decimal(30,0))+1)as varchar),@iLen)
set @SQLString='select @vIncrement=right(''000''+cast((cast(substring(@vTempID,1,'+cast(@iLen as varchar)+') as decimal(30,0))+1)as varchar),'+cast(@iLen as varchar)+')'
exec sp_executesql @SQLString
,N'@vIncrement varchar(30) output,@vTempID varchar(30)'
,@vIncrement out,@vTempID print 'test 3'
end
end
go