存储过程中有如下逻辑的语句:
IF ISNULL(@x,'') = ''
BEGIN SELECT v.*
INTO #T
FROM vEND
ELSE
BEGIN SELECT v.*
INTO #T
FROM vEND
当建立存储过程的时候提示错误:
消息 2714,级别 16,状态 1,过程 usp_sp,第 44 行
数据库中已存在名为 '#T' 的对象。
错误指向else中的into语句行。

解决方案 »

  1.   

    IF ISNULL(@x,'') = ''
    BEGIN
    exec('if object_id(''tempdb..#t'')is not null drop table tempdb..#t')
        SELECT v.*
        INTO #T
        FROM vEND
    ELSE
    BEGIN
    exec('if object_id(''tempdb..#t'')is not null drop table tempdb..#t')
        SELECT v.*
        INTO #T
        FROM vEND
      

  2.   

    USE tempdb
    go
    DECLARE @x NVARCHAR(10)
    IF ISNULL(@x,'') = ''
    BEGIN    SELECT v.*
        INTO #T
        FROM vEND
    ELSE
    BEGIN
    EXEC('
        SELECT v.*
        INTO #T
        FROM v')END
      

  3.   


    实际上这是出于ifelse分支内的事情,怎么sqlserver也不判断这种情况哪?
    是不是它只当所有的代码都顺序执行哪?
      

  4.   


    up,说到底还是SQL不够智能。
      

  5.   

    这个方法解决了语句问题,但不同会话能访问到tempdb.dbo.t,在并发处理时也会有问题。如果用newid()生成表名或许可以变通解决。
      

  6.   

    根本原因是sql不支持临时表的滞后名称解析,但永久表是可以的
      

  7.   

    在存储过程中慎用SELECT INTO。
    CREATE TABLE #T(...)
    IF ISNULL(@x,'') = ''
    BEGIN
        INSERT INTO #T
        SELECT v.*
        FROM v
    END
    ELSE
    BEGIN
        INSERT INTO #T
        SELECT v.*
        FROM v
    END
      

  8.   

    如果FROM的表是v1,v2,而且两个表结构不同,就不能事先创建好表结构了。可以考虑用不同的临时表名区分开。
      

  9.   

    迂回的解决方式有:
    create table #T 再在分支中alter table #T
    或者可以把if 和else中的语句分别写在不同的存储过程中,再用第三个存储过程来访问#T
      

  10.   


    我也在考虑 insert into 的实现方式。
    INSERT INTO #T 的时候错误:
    消息 213,级别 16,状态 1,过程 usp_sp,第 30 行
    插入错误: 列名或所提供值的数目与表定义不匹配。INSERT INTO #T(ku) 的时候错误:
    消息 207,级别 16,状态 1,过程 usp_sp,第 30 行
    列名 'ku' 无效。把临时表的列写出来它会认为没有,不写出来它认为不匹配。
    不使用exec的话,就没有办法了吗?
      

  11.   

    使用insert into方式搞定,之前说有错误:“INSERT INTO #T(ku) 的时候错误:
    消息 207,级别 16,状态 1,过程 usp_sp,第 30 行
    列名 'ku' 无效。”原因是在查询分析器里建了一个 #T,但是结构又不正确,查询分析器拿来做比较,所以就出错了。