【问题标题】:SQL: delete all the data from all available tablesSQL:删除所有可用表中的所有数据
【发布时间】:2018-02-12 18:29:12
【问题描述】:

我使用oracle DB维护了30多张表,如何删除所有表中的所有数据?我只想删除数据而不删除表。

【问题讨论】:

  • 这个问题似乎是题外话,因为它属于 dba.stackexchange.com

标签: sql oracle


【解决方案1】:

没有命令'ALTER TABLE XXX DISABLE ALL CONSTRAINTS'

我提出这个建议;

BEGIN
  FOR c IN (SELECT table_name, constraint_name FROM user_constraints WHERE constraint_type = 'R')
  LOOP
    EXECUTE IMMEDIATE ('alter table ' || c.table_name || ' disable constraint ' || c.constraint_name);
  END LOOP;
  FOR c IN (SELECT table_name FROM user_tables)
  LOOP
    EXECUTE IMMEDIATE ('truncate table ' || c.table_name);
  END LOOP;
  FOR c IN (SELECT table_name, constraint_name FROM user_constraints WHERE constraint_type = 'R')
  LOOP
    EXECUTE IMMEDIATE ('alter table ' || c.table_name || ' enable constraint ' || c.constraint_name);
  END LOOP;
END;

【讨论】:

  • 这个解决方案可能不是投票最多的,因为人们不想在这里阅读所有答案。
  • 这应该是一个更好的解决方案。您还可以将其调整为实际 DROP TABLES 和 CONSTRAINTS 而不是 TRUNCATE。
【解决方案2】:

生成一个脚本来截断(= 删除所有行)所有表:

select 'truncate table ' || table_name || ';' from user_tables

然后执行脚本。

【讨论】:

  • 我确实编辑了这个答案,对此感到抱歉,但 all_tables 的事情非常危险。
  • 仅适用于新手:注意truncate 是非事务性的,即不能回滚。
  • 如果定义了外主键约束,这将不起作用。
【解决方案3】:

为了解决约束问题,这样的事情应该可以工作:

BEGIN

    FOR T in (SELECT table_name FROM user_tables) LOOP
      EXECUTE IMMEDIATE 'ALTER TABLE '||T.table_name||' DISABLE ALL CONSTRAINTS';
    END LOOP;

    FOR T in (SELECT table_name FROM user_tables) LOOP
      EXECUTE IMMEDIATE 'TRUNCATE TABLE '||T.table_name;
    END LOOP;

    FOR T in (SELECT table_name FROM user_tables) LOOP
      EXECUTE IMMEDIATE 'ALTER TABLE '||T.table_name||' ENABLE ALL CONSTRAINTS';
    END LOOP;
END;

【讨论】:

  • 如果没有为表定义约束,alter table ... disable all constraints 会抛出 ORA-01735: invalid ALTER TABLE option,这将导致脚本无法截断 每个 表(如果至少有一个)没有约束的表。您可能希望将 execute immediate 放在 begin .. exception 块中。
【解决方案4】:

截断的潜在缺点是它可能会在参照完整性约束上失败。因此,您首先要禁用外键约束,然后进行截断,然后重新启用约束。 克隆模式(exp 和 imp)的“加号”是你也可以删除并重新创建表空间(如果你想回收一些物理磁盘空间作为删除所有数据的结果,你可能想要这样做)。

【讨论】:

    【解决方案5】:

    克隆架构然后删除旧表?

    【讨论】:

    • 或者“真正的 DBA”的做法:备份完整的 DB 没有数据,然后重建 DB(...服务器...从主板开始;)。
    • @TomH。这怎么简单?我不是 DBA,它让我不知道要执行什么命令。
    • @FarmBoy,将依赖 DBMS 的 IIRC。
    • @TomH。这是一个甲骨文问题。 . .
    【解决方案6】:

    我使用上面提到的答案创建了这个存储过程。 这可以完美运行,没有任何错误或异常。

        create or replace PROCEDURE DELETE_ALL_DATA
    AS 
    cursor r1 is select * from user_constraints;
    cursor r2 is select * from user_tables;
    cursor r3 is select * from user_constraints;
    cursor r4 is select * from user_tables;
    
    BEGIN
    
        FOR c1 IN r1
      loop
        for c2 in r2
        loop
            begin
           if c1.table_name = c2.table_name and c1.status = 'ENABLED' THEN
            dbms_utility.exec_ddl_statement('alter table ' || c1.owner || '.' || c1.table_name || ' disable constraint ' || c1.constraint_name);
           end if;
            EXCEPTION
             WHEN NO_DATA_FOUND
               THEN
               continue;
             WHEN OTHERS 
               THEN
               continue;
               end;
        end loop;
      END LOOP;
    
        FOR T in (SELECT table_name FROM user_tables) LOOP
          begin
          EXECUTE IMMEDIATE 'TRUNCATE TABLE '||T.table_name;
          EXCEPTION
             WHEN NO_DATA_FOUND
               THEN
               continue;
             WHEN OTHERS 
               THEN
               continue;
               end;
        END LOOP;
    
        FOR c1 IN r3
      loop
        for c2 in r4
        loop
            begin
           if c1.table_name = c2.table_name and c1.status = 'DISABLED' THEN
            dbms_utility.exec_ddl_statement('alter table ' || c1.owner || '.' || c1.table_name || ' enable constraint ' || c1.constraint_name);
           end if;
            EXCEPTION
             WHEN NO_DATA_FOUND
               THEN
               continue;
             WHEN OTHERS 
               THEN
               continue;
               end;
        end loop;
      END LOOP;
    
        commit;
    END DELETE_ALL_DATA;
    

    【讨论】:

      【解决方案7】:

      Andomar 的答案略有不同,即截断特定用户的所有表,而不是仅截断当前用户的表:

      SELECT 'TRUNCATE TABLE ' || owner || '.' || table_name || ';' FROM all_tables WHERE owner = 'user/schema'
      

      将上面的user/schema 位替换为您感兴趣的用户/模式的名称(在引号之间)。

      【讨论】:

      • 感谢这个查询对我的帮助很大。如果你有超过 1 个 db/schema,我更喜欢这个查询
      【解决方案8】:

      删除oracle中所有表的所有数据

      声明
        str VARCHAR2(100);
      开始
        为我输入
        (从 user_objects 中选择 object_name,其中 object_type='TABLE'
        )
        环形
          str := '截断表'|| i.object_name;
          立即执行 str;
          DBMS_OUTPUT.PUT_LINE('表数据已删除:' || i.object_name);
        结束循环;
      结束;

      欲了解更多信息:http://www.oracleinformation.com/2014/10/delete-all-the-data-from-all-tables.html

      【讨论】:

        【解决方案9】:

        这两行脚本最好

        EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
        GO
        
        EXEC sp_MSForEachTable 'DELETE FROM ?'
        GO
        

        【讨论】:

        • 这是截断 Microsoft SQL Server 数据库中所有表的最简单方法。即使您在删除数据后忘记重新启用约束。但是......这个问题是关于 Oracle ......而不是 SQL Server。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多