慎用create table as select,一定要注意默认值的问题

本文探讨了使用CTAS(Createtableasselect)进行数据迁移时的潜在问题,特别是默认值和约束的丢失,以及如何避免这些问题。同时,讨论了CTAS在不同Oracle版本中的行为差异,以及如何通过调整表结构、禁用约束和使用提示来优化数据迁移性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

慎用create table as select,一定要注意默认值的问题

2013年11月28日 10:44:45 haiross 阅读数:120517

摘要:

1、再做一些数据迁移时候,很多人会使用create table  as select * from table where id=-1的方式来年建立一摸一样的表,但是这样做有个很大的弊端,不能将原表中的default value也一同迁移过来

2、  Using the CREATE TABLE ... AS SELECT ... command: This command will copy acrooss to the new table all the data,but the constraints triggers ,and so on will not be transferred to the new table.

        那些都是not null约束,其他的约束和trigger是带不过来了,严格说来not null也是约束的一种,只不过教材上把它排除在外了吧。

慎用create table as select,一定要注意默认值的问题

博客分类:  Oracle

oraclecreate talbe as select数据库迁移 

再做一些数据迁移时候,很多人会使用create table  as select * from table where id=-1的方式来年建立一摸一样的表,但是这样做有个很大的弊端,不能将原表中的default value也一同迁移过来,可以看下面的例子:

 

第一,新建一个表

 

-- Create table
create table table01
(
  id        number(16),
  add_date  date default sysdate,
  status    number(1),
  entp_code varchar2(200)
)

 

第二,使用create table table02 as
select * From table01 where id=-1

 

第三、看看两个表的结构,会发现第二张表的defaule value没有了,如下2图,可以很明显看出来,表02的add_date的默认值得sysdate没有了

table01的表结构

 table02的表结构


 

所以各位在做数据库迁移时候,使用create table as select时候,一定要注意默认值的问题

 

上周,因为此问题,导致生产环境下产生了大量的问题,头大了一天,特此奉献出来。

====================================================================

 

Create table as select 语句的两点说明

SQL > create table emp_copy as select * from emp where deptno=10;

第一,注意emp_copy表中没有定义任何列名,因为我们在列子句中用通配符从emp表取得数据,让Oracle像emp表中一样生成emp_copy表中的列——相同名称,相同数据类型定义。

第二,SQL*PLUS中可以发出的任何select语句可以放在create table as select 语句中,然后Oracle会自动获得从emp表选择的数据,在进emp_copy表中。但是 如果select语句的列子句中包括特定列清单,则create table子句要列出表中要包括的列,放在括号中,例如:

SQL > create table emp_copy_2 (empno,sal) as select empno, sal from emp where deptno=10;

========================================================

 

create table as select 2010-04-18 11:39:26

分类: Linux

大家都知道create table a as select * from b可以创建一个与b表结构一样的表,但是在实际应用中最好不要这么创建表。原因是这样只创建表的结构,而不会将原表的默认值一起创建。

说白了,表结构出来了,默认值没有。

另外,但是有一个我对一个大表执行create table a as select * from b时候报了一个temp表空间不足,不知道是什么原因,记录一下。下次发现在处理吧。

 

转载http://space.itpub.net/9252210/viewspace-660173

----------------------------------------

 

一、Symptoms
        During CTAS (CREATE TABLE AS SELECT), be reported:
       ORA-01652: unable to extend temp segment by 1024 in tablespace <DATA>

二、Cause
        The tablespace where the object is being created doesnt have sufficient space to extend for the CTAS command to succeed.

三、Solution
        Modify the datafile associated for the tablespace to AUTOEXTEND ON till the CTAS command gets executed successfully.
       During the CTAS , it creates a data segment in the target tablespace and marks this segment as temporary in dictionary.
       Once the table created successfully , the dictionary type is changed from TEMPRORAY to TABLE. In addition, if the SELECT performs a SORT operation,temporary space may be used as for the same.

四、TEST CASE
       1. 创建表空间
          SQL> CREATE TABLESPACE TEST DATAFILE 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL10G\TEST.DBF' SIZE 10M AUTOEXTEND OFF;
           Tablespace created
        2. 为客户分配默认表空间
          SQL> ALTER USER TESTER DEFAULT TABLESPACE TEST;
           User altered.
        3. 查询对象实际大小
         SQL>SELECT BYTES/1024/1024,TABLESPACE_NAME FROM DBA_SEGMENTS WHERE SEGMENT_NAME='DUMMY';
                     11       system    --Size of the DUMMY object is 11 M
       4. CTAS创建新对象
          SQL> CONN TESTER/TESTER
                      Connected.
           SQL> CREATE TABLE DUMMY_123 AS SELECT * FROM SCOTT.DUMMY;
           CREATE TABLE DUMMY_123 AS SELECT * FROM SCOTT.DUMMY
           *
           ERROR at line 1:
           ORA-01652: unable to extend temp segment by 128 in tablespace TEST
      The above error message reported above is because the Tablespace TEST is of 10 M size and AUTOEXTEND OFF. The object about to be created "DUMMY_123 " , requires 11 M size and as it doesn't have enough space to extend , it has failed with the ORA-1652 error message in "TEST" tablespace.

一、Temporary Segments Concept
        Oracle often requires temporary work space for intermediate stages of database processing. There are different kinds of temporary segments in the database.
        Some of them are created explicitly by the users. The others are created and accessed for the user by the system.
       There are SQL operations containing a sorting step which require temporary segments. However, segments used for sorting are not the only segments having SEGMENT_TYPE=TEMPORARY. Temporary segments can also exist for permanent segments creation.

      Temporary segments for sorting are created in the default temporary tablespace of the user. This tablespace may be of type TEMPORARY or PERMANENT.
      (1)  A TEMPORARY tablespace (Locally Managed Tablespace) is recommended for sort operations.
      (2)  Temporary segments for permanent segments creation are created in the tablespace specified in the create statement or in the user’s default tablespace.

a.  Temporary Tables
     only exists during a transaction or session.
     DML statements on temporary tables do not generate redo logs for the data changes. However, undo logs for the data and redo logs for the undo logs are generated.
   
b.  Temporary LOBs
     The goal of temporary LOBs is to develop an interface to support the creation and deletion of lobs that act like local variables.
   
c.  Temporary Segments as work area for sorting
     When processing queries, Oracle often requires temporary workspace for intermediate stages of SQL statement execution.
     The sort area is allocated in memory. If the sort operation needs additional memory (above the value specified by the SORT_AREA_SIZE parameter), the sorted rows are written to disk to free up the sort area so that it can be re-used for the remaining sort.
    Oracle automatically allocates this disk space called a temporary segment.
    The following statements may require the use of a temporary segment for sorting:
   CREATE INDEX/SELECT ... ORDER BY/SELECT DISTINCT/SELECT ... GROUP BY/SELECT ... UNION/SELECT ... INTERSECT/SELECT ... MINUS/ANALYZE TABLE/Unindexed joins/Correlated subqueries

d.  Temporary Segments for permanent segments creation
     Besides sort operations, there are other SQL operations, which also require temporary segments:
   CREATE PRIMARY/UNIQUE KEY CONSTRAINT
    ALTER TABLE ... ENABLE PRIMARY/UNIQUE CONSTRAINT
    CREATE TABLE STORAGE (MINEXTENTS>1)
    CREATE TABLE AS SELECT
           The CTAS creates a data segment in the target tablespace and marks this segment as temporary in dictionary.
           On completion, the dictionary type is changed from temporary to table. In addition, if the SELECT performs a SORT operation, temporary space may be used as for a standard select.
   CREATE PARTITION TABLE
    ALTER TABLE ... SPLIT PARTITION
    CREATE SNAPSHOT
    CREATE INDEX
           The CREATE INDEX statement, after sorting the index values, builds a temporary segment in the INDEX tablespace;
           once the index is completely built, the segment type is changed to INDEX.
    DROP TABLE  
   
e.  Temporary Tablespaces

二、Introduction to Direct-Path INSERT
        1. Conventional insert operations:
            Oracle reuses free space in the table, interleaving newly inserted data with existing data. During such operations, Oracle also maintains referential integrity constraints.

        2. Direct-path INSERT operations:
           Oracle appends the inserted data after existing data in the table. Data is written directly into datafiles, bypassing the buffer cache. Free space in the existing data is not reused, and referential integrity constraints are ignored. These procedures combined can enhance performance.
            a. During direct-path INSERT, you can disable the logging of redo and undo entries
            b.CREATE TABLE ... AS SELECT statement, does not have any indexes defined on it and not null constraint; you must define them later.
  
Note:If the database or tablespace is in FORCE LOGGING mode, then direct path INSERT always logs, regardless of the logging or nologging setting, such as STANDBY database.

 

 

========================================================

 

Create table as select性能简介:

在数据库中移动数据最快的方法是将其从一个表移动到别一个表,而不是需要进入操作系统将数据从一个表移动到别一个表,有一些常见的方法可用于提高数据迁移的性能:

1.             调整表的结构(删除索引和触发器)

2.             在数据迁移期间禁用约束

3.             使用提示和选项来改进事务性能

第一个技巧是调整表的结构,它涉及禁用目标表上面的任何触发器或索引。例如,如果在目标表上有行级触发器,则插入到表中的每一行都会执行触发器。如果可能的话,最好在数据插入之前将目标表的触发器禁用;如果应该为每个插入的行执行该触发器,则可以在批量插入完成以后再创建此触发器,而不应该在批量插入期间每插入一条数据重复执行触发器。

除了禁用触发器,应该在启动数据加载之前删除目标表上面的索引,然后在数据加载完毕后再重新创建索引。如果索引留在表上,ORACLE将在插入每一行时动态管理索引。

注意:删除索引和禁用触发器可以解决大多数数和大型表与表之间数据迁移中遇到的性能问题。

除了禁用索引,还要考虑到表上的约束。如果源数据已经在数据库的表中,在将数据加载到目标表之前,可以检查该数据了解它的相关约束(例如外键或check约束),一旦加载数据完成就可以重新启用这些约束。

如果以上选项无法提供适当的性能,就应该调查Oracle为数据迁移调整引入的选项。这些选项包括如下:

1.插入命令的APPPEND提示   类似于Direct Path Loader,APPENED提示将数据块加载到表中,从表的高水位线开始。使用APPENED提示可以增加空间利用率。

2.Nologging选项  如果正在执行create table as select 命令,使用nologing选项可避免在操作期间写入重做日志文件。

3.并行选项   并行查询使用多个进程来完成一个任务。对于create table as select命令,可并行化create table 部分和查询部分。如果使用并行选项,则也应该使用nologing选项,否则并行操作将不得不由于串行化写入到联机重做日志文件而等待。

在使用这些高级选项之前,应该首先调查目标表的结构,确保已经避免前面提到的一些常见问题。

分享到:        

阅读(2376)| 评论(0)| 转载 (0) |举报

 

ORALCE DBMS_STATS与ANALYZE介绍

 

 

========================================================

今天鄙人有意翻出ORACLE 9I Performance Tuning  的官方教材,看到原文:
  Using the CREATE TABLE ... AS SELECT ... command: This command will copy acrooss to the new table all the data,but the constraints triggers ,and so on will not be transferred to the new table.

  但本人在自己的生产库的操作过程中,发现,只要是用as select CREATE的表,都是带有原表的CONSTRINTS....

有谁能解释一下,.

这难道是官方文件的手误???

 

 

 

Connected to Oracle9i Enterprise Edition Release 9.2.0.4.0 
Connected as serp01

SQL> select constraint_name from dba_constraints where table_name ='CRM_CUSTOMER';

CONSTRAINT_NAME
------------------------------
REFCRM_CUSTOMER2167
REFINV_WAREHOUSE482
REFINV_WAREHOUSE608
REFORG_EMPLOYEES0001
REFORG_EMPLOYEES1474
REFORG_ENTERPRISES1400
REFORG_ORGANIZATIONS000001
REFORG_ORGANIZATIONS2401
REFPUB_AREA_CODE379
REFPUB_CLASSIFY_CODE380
REFPUB_ENTERPRISE_TYPE_CODE381
REFPUB_INDUSTRY_CODE382
REFPUB_PAYCONDI_CODE0000001
REFTPUB_PAYMENT_CODE01
SYS_C0092306
SYS_C0092764
SYS_C0079060
SYS_C0079061
SYS_C0079062
SYS_C0079063

CONSTRAINT_NAME
------------------------------
SYS_C0079064
SYS_C0079065
SYS_C0079066
SYS_C0079067
SYS_C0079068
SYS_C0079069
SYS_C0079070
SYS_C0079071
SYS_C0079072
SYS_C0079073
SYS_C0079074
SYS_C0079075
SYS_C0079076
SYS_C0079077
SYS_C0079078
SYS_C0079079
SYS_C0079080
SYS_C0079081
SYS_C0079082
SYS_C0079083
SYS_C0079084

CONSTRAINT_NAME
------------------------------
SYS_C0079085
SYS_C0079086
SYS_C0079087
SYS_C0079088
SYS_C0079089
SYS_C0079090
SYS_C0079091
SYS_C0079092
SYS_C0079093
SYS_C0079094
SYS_C0079095
SYS_C0079096
SYS_C0079097
SYS_C0079098
SYS_C0079099
SYS_C0079100
SYS_C0079101
SYS_C0079102
SYS_C0079103
SYS_C0079104
SYS_C0079105

CONSTRAINT_NAME
------------------------------
SYS_C0079106
SYS_C0079107
SYS_C0079108
SYS_C0079109
PK19

67 rows selected

SQL> create table temp_h1 as select * from crm_customer where rownum<10;

create table temp_h1 as select * from crm_customer where rownum<10

ORA-00955: 名称已由现有对象使用

SQL> drop table temp_h1;

Table dropped

SQL> create table temp_h1 as select * from crm_customer where rownum<10;

Table created

SQL> select constraint_name from dba_constraints where table_name ='TEMP_H1';

CONSTRAINT_NAME
------------------------------
SYS_C0093440
SYS_C0093441
SYS_C0093442
SYS_C0093443
SYS_C0093444
SYS_C0093445
SYS_C0093446
SYS_C0093447
SYS_C0093448
SYS_C0093449
SYS_C0093450
SYS_C0093451
SYS_C0093452
SYS_C0093453
SYS_C0093454
SYS_C0093455
SYS_C0093456
SYS_C0093457
SYS_C0093458
SYS_C0093459

CONSTRAINT_NAME
------------------------------
SYS_C0093460
SYS_C0093461
SYS_C0093462
SYS_C0093463
SYS_C0093464
SYS_C0093465
SYS_C0093466
SYS_C0093467
SYS_C0093468
SYS_C0093469
SYS_C0093470
SYS_C0093471
SYS_C0093472
SYS_C0093473
SYS_C0093474
SYS_C0093475
SYS_C0093476
SYS_C0093477
SYS_C0093478
SYS_C0093479
SYS_C0093480

CONSTRAINT_NAME
------------------------------
SYS_C0093481
SYS_C0093482
SYS_C0093483
SYS_C0093484
SYS_C0093485
SYS_C0093486
SYS_C0093487
SYS_C0093488
SYS_C0093489
SYS_C0093490
SYS_C0093491

52 rows selected

SQL>
 
  


A答:也许你有好几个TEMP_H1, 在不同的SCHEMA里.  试试

select owner, table_name from dba_tables where table_name ='TEMP_H1';

就会一目了然

 

B答:这个是不可能的,用ctas从组表必然要对表加相应的约束等。。。。

 

 

C答:那些都是not null约束,其他的约束和trigger是带不过来了,严格说来not null也是约束的一种,只不过教材上把它排除在外了吧。


另见:

SELECT INTO 和 INSERT INTO SELECT 两种表复制语句

<think>我们正在处理一个外键约束冲突问题,具体错误信息是: "The INSERT statement conflicted with the FOREIGN KEY constraint 'FK_tbIElementParameters_tblDataTypes'. The conflict occurred in database 'DB130A00', table 'dbo.tblDataTypes', column 'DataTypelD'." 根据错误信息,我们在向表`tblElementParameters`插入数据时,提供的`DataTypelD`值在父表`tblDataTypes`中不存在。 ### 解决步骤 #### 步骤1: 确认外键关系 首先,我们需要确认外键约束的具体细节,包括它关联的两个表和列。 ```sql -- 查询外键约束信息 SELECT fk.name AS ConstraintName, OBJECT_NAME(fk.parent_object_id) AS ChildTable, c1.name AS ForeignKeyColumn, OBJECT_NAME(fk.referenced_object_id) AS ParentTable, c2.name AS PrimaryKeyColumn FROM sys.foreign_keys fk INNER JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id INNER JOIN sys.columns c1 ON fkc.parent_object_id = c1.object_id AND fkc.parent_column_id = c1.column_id INNER JOIN sys.columns c2 ON fkc.referenced_object_id = c2.object_id AND fkc.referenced_column_id = c2.column_id WHERE fk.name = 'FK_tbIElementParameters_tblDataTypes'; ``` #### 步骤2: 检查插入值 确认插入语句中提供的`DataTypelD`值是否存在于父表`tblDataTypes`中。 ```sql -- 检查插入的DataTypelD值是否在父表中存在 SELECT DataTypelD FROM tblDataTypes WHERE DataTypelD IN ( /* 这里放入你要插入的DataTypelD值 */ ); ``` 如果查询结果为空,说明插入的值确实不存在于父表中。 #### 步骤3: 解决方案 根据检查结果,选择以下解决方案: ##### 方案1: 在父表中添加缺失的值 如果插入的值是合理的,但父表中缺失,那么先向父表插入这些值。 ```sql -- 向tblDataTypes插入缺失的DataTypelD INSERT INTO tblDataTypes (DataTypelD, ...) -- 其他必要的列 VALUES (缺失的值, ...), ...; ``` 然后重新执行原来的插入操作。 ##### 方案2: 修改插入的值 如果插入的值有误,应该修改为父表中存在的值。 ##### 方案3: 临时禁用外键约束(不推荐) 在极特殊情况下,如果确定可以忽略外键约束(例如数据迁移),可以临时禁用外键约束,但完成后必须重新启用并检查数据完整性。 ```sql -- 禁用外键约束 ALTER TABLE tblElementParameters NOCHECK CONSTRAINT FK_tbIElementParameters_tblDataTypes; -- 执行插入操作 INSERT INTO tblElementParameters ...; -- 重新启用外键约束 ALTER TABLE tblElementParameters CHECK CONSTRAINT FK_tbIElementParameters_tblDataTypes; -- 检查数据完整性 DBCC CHECKCONSTRAINTS('tblElementParameters'); ``` > **警告**:禁用约束可能导致数据不一致,应谨慎使用。 #### 步骤4: 预防措施 为避免未来出现类似问题: 1. **应用层验证**:在应用程序中,插入前检查外键值是否存在。 2. **数据库设计**:考虑使用默认值或设置外键列为可空(如果业务允许),并设置适当的更新/删除规则(如`ON UPDATE CASCADE`或`ON DELETE SET NULL`)[^2]。 3. **使用事务**:在插入相关数据时,使用事务确保要么全部成功,要么全部回滚。 ### 相关问题 1. 如何查询SQL Server中所有失效的外键约束? 2. 外键约束的`ON UPDATE CASCADE`和`ON DELETE CASCADE`有何区别?[^2] 3. 如何批量修复数据库中已存在的无效外键数据? 4. SQL Server外键约束与触发器在数据完整性维护中的优劣比较? ### 附加说明 - 如果外键列允许NULL值,插入NULL不会违反约束(因为NULL表示未知,不引用任何值)[^3]。 - 删除操作时也可能遇到类似约束冲突(如引用父表记录的删除),此时需先删除子表记录或设置级联删除[^4]。 请根据实际业务情况选择最合适的解决方案。</think>### 解决 SQL Server 外键约束冲突的完整指南 当出现错误 **"INSERT statement conflicted with FOREIGN KEY constraint FK_tblElementParameters_tblDataTypes"** 时,表明您正在尝试向子表(`tblElementParameters`)插入的数据引用了父表(`tblDataTypes`)中不存在的外键值。以下是系统化的解决方案: --- ### 一、问题根源分析 1. **外键约束原理** 子表的外键字段(`DataTypeID`)必须引用父表(`tblDataTypes`)中已存在的值[^2]。错误直接指出冲突发生在`DataTypeID`列: ```sql FOREIGN KEY (DataTypeID) REFERENCES tblDataTypes(DataTypeID) ``` 2. **具体冲突原因** - 插入的`DataTypeID`值在`tblDataTypes`中不存在 - 父表对应记录已被删除而子表仍有引用[^4] - 数据类型不匹配(如字符串与数字) - 空值处理不当(NULL 可能被允许,但空字符串''会报错)[^3] --- ### 二、诊断步骤 #### 步骤1:确认外键关系 ```sql -- 查询约束关联的列 SELECT fk.name AS ConstraintName, OBJECT_NAME(fk.parent_object_id) AS ChildTable, c1.name AS ForeignKeyColumn, OBJECT_NAME(fk.referenced_object_id) AS ParentTable, c2.name AS PrimaryKeyColumn FROM sys.foreign_keys fk INNER JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id INNER JOIN sys.columns c1 ON fkc.parent_object_id = c1.object_id AND fkc.parent_column_id = c1.column_id INNER JOIN sys.columns c2 ON fkc.referenced_object_id = c2.object_id AND fkc.referenced_column_id = c2.column_id WHERE fk.name = 'FK_tblElementParameters_tblDataTypes' ``` #### 步骤2:检查无效数据 ```sql -- 查找子表中无效的外键值 SELECT DISTINCT ep.DataTypeID FROM tblElementParameters ep LEFT JOIN tblDataTypes dt ON ep.DataTypeID = dt.DataTypeID WHERE dt.DataTypeID IS NULL ``` #### 步骤3:验证插入数据 ```sql -- 检查待插入值是否存在于父表 DECLARE @InsertValue INT = 123; -- 替换为实际插入值 IF NOT EXISTS(SELECT 1 FROM tblDataTypes WHERE DataTypeID = @InsertValue) PRINT '错误:值 ' + CAST(@InsertValue AS VARCHAR) + ' 在父表中不存在'; ``` --- ### 三、解决方案 #### ✅ 方案1:修复数据(推荐) ```sql -- 先向父表插入缺失值 INSERT INTO tblDataTypes (DataTypeID, TypeName) VALUES (101, 'Float'), (102, 'Integer'); -- 补充缺失的值 -- 再执行原插入语句 INSERT INTO tblElementParameters (..., DataTypeID, ...) VALUES (..., 101, ...); ``` #### ⚠️ 方案2:临时禁用约束(慎用) ```sql -- 禁用约束 ALTER TABLE tblElementParameters NOCHECK CONSTRAINT FK_tblElementParameters_tblDataTypes; -- 执行插入 INSERT INTO tblElementParameters (...) VALUES (...); -- 重新启用约束 ALTER TABLE tblElementParameters CHECK CONSTRAINT FK_tblElementParameters_tblDataTypes; -- 必须立即修复无效数据! ``` > **警告**:禁用约束后需立即修复数据,否则会导致数据不一致[^4] #### 🔄 方案3:级联操作(设计优化) ```sql -- 修改约束添加级联 ALTER TABLE tblElementParameters DROP CONSTRAINT FK_tblElementParameters_tblDataTypes; ALTER TABLE tblElementParameters ADD CONSTRAINT FK_tblElementParameters_tblDataTypes FOREIGN KEY (DataTypeID) REFERENCES tblDataTypes(DataTypeID) ON UPDATE CASCADE -- 父表更新时自动更新子表 ON DELETE SET NULL; -- 父表删除时子表设为NULL ``` > **注意**:使用`SET NULL`需确保外键列允许NULL[^2] --- ### 四、预防措施 1. **应用层验证** 在代码中预先检查外键值是否存在: ```csharp // C# 示例 if(!dbContext.tblDataTypes.Any(d => d.DataTypeID == inputTypeId)) { throw new Exception($"无效的DataTypeID: {inputTypeId}"); } ``` 2. **使用事务保证原子性** ```sql BEGIN TRANSACTION INSERT INTO tblDataTypes (DataTypeID, TypeName) VALUES (105, 'Decimal') INSERT INTO tblElementParameters (ParamName, DataTypeID) VALUES ('Price', 105) COMMIT TRANSACTION ``` 3. **空值处理策略** - 允许NULL:`DataTypeID INT NULL` - 设置默认值:`DataTypeID INT NOT NULL DEFAULT 0` > 注意:空字符串('')会触发约束失败,而NULL可能被允许[^3] --- ### 五、错误场景模拟 ```sql -- 创建测试表 CREATE TABLE tblDataTypes ( DataTypeID INT PRIMARY KEY, TypeName VARCHAR(50) ); CREATE TABLE tblElementParameters ( ParamID INT PRIMARY KEY, DataTypeID INT FOREIGN KEY REFERENCES tblDataTypes(DataTypeID) ); -- 触发错误(父表无ID=99的记录) INSERT INTO tblElementParameters VALUES (1, 99); /* 错误消息: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_tblElementParameters_tblDataTypes" */ ``` --- ### 相关问题 1. 如何查询 SQL Server 中所有失效的外键约束? 2. 外键约束的 `ON UPDATE CASCADE` 和 `ON DELETE CASCADE` 有何区别?[^2] 3. 如何批量修复数据库中已存在的无效外键数据? 4. SQL Server 外键约束与触发器在数据完整性维护中的优劣比较? 5. 当外键列允许 NULL 值时,插入 NULL 和空字符串('')有何不同行为?[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值