1、多了一个右扩号 !
      as decimal(@iLen,0))+1))as 应改为 as decimal(@iLen,0))+1) as2、decimal、varchar 中好像不让用变量

解决方案 »

  1.   

    帮你改一个地方:
    表名变量不要传递,只能连接字符串生成
    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
      

  2.   

    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
      

  3.   

    两个地方,同样修改: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)
      

  4.   

    第二个是因为你有@vTempID变量要传出,所以用 sp_executesql N'@vTempID varchar(20) output '是SP_executesql内部量.用来OUTPUT结果.@vTempID  output 你存储过程的变量用来接收传出
      

  5.   

    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 字符串相似,所以查询优化程序更有可能反复使用执行计划。
      

  6.   

    想请问前辈
    ////////////////////////////////////////////////////////////////////////////
    帮你改一个地方:
    表名变量不要传递,只能连接字符串生成
    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的联机帮助,我更加迷惑了。还有呀,联机帮助里面好像对每个变量都用参数传递的,为何我的存储过程有的传,有的不传,到底怎么一个规则呀
      

  7.   

    想请问sp_executesql中参数的使用
      1)如果在SQL语句中两次用到同一个表名变量,那么在参数中是不是要说明两次?
      2)另外SQL语句中的每个变量是不是都要在参数列表中说明一下?
      

  8.   

    你还没理解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
      

  9.   

    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。
      

  10.   

    哈哈,不客气,
    反正我现在没什么事。我看你发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了。
      

  11.   

    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我联机帮助看了半天,却仍不知是为什么?向高手请教,再次感谢
      

  12.   

    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这段代码已经完整实现了,经过多次测试,确保无误
      

  13.   

    关键技术说明
    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种
      

  14.   

    /*--共计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