db2 alter 以及 db2 constraint

本文详细介绍了在DB2数据库中如何设置主键、添加非空约束,并通过实例展示了如何处理约束冲突及删除约束的过程。

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

 

--以下语句都是在db2中运行的结果,其他的数据库不保证正确。

DROP TABLE DQ;

DROP TABLE STU;

 

create table dq (dqno int,dqname char(10));

--建表时不指定任何约束。

insert into dq values (1,'beijing');

insert into dq values (2,'shanghai');

insert into dq values (3,'hangzhou');

     --插入三条记录。

select * from dq;

 

现在想制定dqno为dq表的主键:

由于db2在指定成为主键前必须要有非空限制,所以先添加非空约束。

alter table dq add constraint CK_SQ1 CHECK(dqno is not null);

     --添加非空约束

insert into dq(dqname) values ('tianjin');

--测试约束是否生效,报错“The requested operation is not allowed because

--a row does not satisfy the check constraint "DB2ADMIN.DQ.CK_SQ1"”。

--证明约束已经生效。

alter table dq add constraint CST_DQ primary key (DQNO);

--添加主键约束。报错:“"DQNO" cannot be a column of a primary key or unique ---key because it can contain null values”???还报错?

--因为db2不识别这样的not null,我们可以drop约束然后使用另一种。

ALTER TABLE DQ drop check CK_SQ1;

--删除约束CK_SQ1

alter table dq alter dqno set not null;

--设置dqno字段的非空属性

reorg table dq;

--db2做过alter以后最好都reorg以下,否则总是容易导致表处于挂起状态而无法进行其--他操作。

alter table dq add constraint CST_DQ primary key (DQNO);

--添加主键约束。

 

 

create table STU

(id int not null primary key,

 sex  char(1) check(sex in ('F','M')),

 name char(20)  default 'no name',

 region int,

 foreign key(region) references dq(dqno)

 ); ---建表时即指定一大堆约束。

 INSERT INTO stu  VALUES (1,'F',NULL,1);

 INSERT INTO stu  VALUES (2,'M',NULL,2);

SELECT * FROM stu;

 

--可以发现name字段插入的都为空,也就是说不是'no name',为什么?

--继续下边:

 INSERT INTO stu(ID,SEX,REGION)  VALUES (3,'M',3);

 SELECT * FROM stu;

 

--可以发现3已经激发默认值了。也就是说如果你向这个字段写入了,不管是null,还是非null,都代表你指定了name字段的值,此时default就不激发。只有当你insert 数据的时候没有指定name字段,此时才激发默认,写入”no name”。

 

--现在把建表时指定的一大堆约束给删除掉。

alter table stu  drop primary key;   --删除主键。

SELECT * FROM STU;

INSERT INTO STU VALUES (1,'F',NULL,1);  ---INSERT 成功,证明主键删除成功,负责会报错,因为已经有一条记录的id为1了。

--想要删除外键要麻烦一些,先找找到外键的名称。

select CONSTNAME FROM syscat.references where tabschema='DB2ADMIN' AND TABNAME='STU';

ALTER TABLE STU DROP FOREIGN KEY SQL120302124448000;

INSERT INTO STU VALUES (1,'F',NULL,10); ---成功,证明外键删除成功,因为dq表中的id是没有10的。

insert into stu(id,sex,region) values(1,'F',1);

select * from stu;  --name默认写入no name ,证明default还在起作用。

alter table stu alter name drop default;  --删除默认约束。

delete from stu where name='no name';

insert into stu(id,sex,region) values(1,'F',1);  ---插入记录

select * from stu;  --再次查看,发现name已经没有默认写入

select * from syscat.colchecks where tabschema='DB2ADMIN' AND TABNAME='STU'; --找出sex的check名称

alter table stu drop constraint SQL120302124447910;   --删除约束。

insert into stu (id,sex) values (3,'h');  ---插入成功,证明sex的约束已经删除。

insert into stu (sex) values ('f');  --报错,id不能插入null 值。

alter table stu alter id drop not null;  ---删除非空限制

reorg table stu;

insert into stu (sex) values ('f');  --插入成功。非空限制删除成功。

--db2修改表名称的方法如下:

--rename table SCHEMA_NAME.OLD_TABLE_NAME to SCHEMA_NAME.NEW_TABLE_NAME ;

rename table stu to student;

--需要指出的的是db2不支持修改表字段名称。如果你非要修改那么只能曲线救国了。

--1)增加一个新列;2)新列值等于要改名的列 3)drop旧列

 

 

删除约束可以参考如下链接:

 

http://www.ibm.com/developerworks/data/library/techarticle/dm-0401melnyk/index.html#N10230

<think>好的,用户现在遇到了DB2的报错138,需要我来帮忙解决。首先,我要回想一下DB2的错误代码对应的含义。我记得SQLCODE -138是跟无效的日期或时间格式有关,可能是在插入或更新数据时,提供的日期或时间值不符合DB2的格式要求。 用户之前询问过如何在DB2中从后往前截取字符串,现在遇到了这个错误,可能是在处理包含日期或时间字段的数据时触发的。比如,用户可能在截取字符串后,尝试将结果转换为日期或时间类型,或者在进行数据操作时涉及到了日期时间字段,但输入的格式不正确。 接下来,我需要确认SQLCODE -138的具体信息。根据DB2文档,这个错误通常是因为字符串无法转换为有效的日期、时间或时间戳。例如,日期格式应该是'YYYY-MM-DD',而用户可能输入了'DD-MM-YYYY'或者其他格式,或者月份、日期超出了合理范围,比如月份为13或者日期为32。 然后,我需要考虑用户可能的场景。用户可能在执行INSERT、UPDATE语句,或者在WHERE子句中比较日期时间字段,或者在调用函数如DATE()、TIMESTAMP()时传入了错误的字符串格式。例如,用户可能在截取字符串后,将结果作为日期使用,但截取后的格式不符合要求。 接下来,我应该提供具体的解决步骤。首先,检查出错的SQL语句,定位到涉及日期时间转换的部分。然后,确认相关字段的值是否符合标准格式。如果用户使用了标准格式,可能需要使用TO_DATE函数进行显式转换,或者调整字符串的格式。 另外,用户可能需要验证数据源中的数据是否有错误,比如错误的日期值。例如,字符串、数字字符或者不合法的日期值。此外,时区问题也可能导致时间戳转换错误,需要检查时区设置是否正确。 还需要提醒用户注意隐式转换的风险,建议使用显式转换函数,并设置正确的日期格式参数。同时,检查数据库的区域设置,确保与输入的日期格式兼容。如果用户是在处理多字节字符,比如中文,还要确保字符串长度和截取操作没有破坏日期格式的结构。 最后,通过示例说明如何修正错误,比如使用TO_DATE函数,或者调整字符串格式,确保用户能够理解并应用解决方案。同时,建议用户在开发过程中进行严格的输入验证和边界测试,避免类似错误的发生。</think>在DB2数据库中,**SQLCODE -138** 是一个与日期时间格式相关的常见错误。以下是该错误的详细解析与解决方案: --- ### 一、错误定义 **SQLCODE = -138** **SQLSTATE = 22007** **错误描述**:`THE VALUE OF INPUT VARIABLE OR PARAMETER <position-number> IS INVALID` **核心原因**:尝试将字符串转换为日期(DATE)、时间(TIME)或时间戳(TIMESTAMP)时,格式不符合DB2规范。 --- ### 二、典型触发场景 #### 1. **直接转换失败** ```sql -- 错误示例 SELECT DATE('2024-13-01') FROM SYSIBM.SYSDUMMY1 -- 月份超过12导致错误 SELECT TIMESTAMP('2024-02-30 25:00:00') FROM SYSIBM.SYSDUMMY1 -- 日期和小时均法(2月无30日,小时最大23) ``` #### 2. **隐式转换错误** ```sql -- 错误示例 CREATE TABLE orders ( order_date DATE ); INSERT INTO orders VALUES ('31/04/2024') -- 使用标准格式'DD/MM/YYYY' ``` #### 3. **动态参数传递** ```sql -- 错误示例(应用程序代码) PreparedStatement ps = conn.prepareStatement( "SELECT * FROM events WHERE event_time > ?" ); ps.setString(1, "2024-05-32 10:00:00"); -- 传入法日期 ``` --- ### 三、解决方案 #### 步骤1:定位错误位置 检查错误信息中的 `<position-number>`,确定具体哪个参数或变量存在问题: ```sql -- 错误消息示例 THE VALUE OF INPUT VARIABLE OR PARAMETER 3 IS INVALID ``` #### 步骤2:验证日期时间格式 DB2严格遵循以下标准格式: | 数据类型 | 合法格式示例 | |----------|-----------------------| | DATE | `'2024-05-21'` | | TIME | `'14:30:45'` | | TIMESTAMP| `'2024-05-21 14:30:45.123456'` | #### 步骤3:显式转换处理 对标准格式使用转换函数: ```sql -- 转换自定义格式 SELECT TO_DATE('21.05.2024', 'DD.MM.YYYY') FROM SYSIBM.SYSDUMMY1 -- 转换带时区的时间戳 SELECT TIMESTAMP_FORMAT('2024/05/21 14-30-45', 'YYYY/MM/DD HH-MM-SS') FROM SYSIBM.SYSDUMMY1 ``` #### 步骤4:检查特殊值 处理边界值和标准输入: ```sql -- 闰年检查 SELECT DATE('2024-02-29') -- 合法(2024是闰年) SELECT DATE('2023-02-29') -- 法(SQLCODE -138) -- 时间溢出检查 SELECT TIME('24:00:00') -- 法(应改为'23:59:59') ``` --- ### 四、高级调试技巧 #### 1. 启用日期格式检查 ```sql -- 设置严格模式(需适当权限) SET DB2_COMPATIBILITY_VECTOR = ORA SET CURRENT DATE FORMAT = 'YYYY-MM-DD' ``` #### 2. 使用错误捕获函数 ```sql -- 验证字符串是否可以转为日期 CREATE FUNCTION is_valid_date(str VARCHAR(20)) RETURNS INT BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN 0; VALUES DATE(str) INTO DUMMY; RETURN 1; END SELECT is_valid_date('2024-13-01') FROM SYSIBM.SYSDUMMY1 -- 返回0 ``` #### 3. 查看系统日历验证 ```sql -- 检查日期是否存在于系统日历 SELECT * FROM SYSCAL.CALENDAR WHERE DATE('2024-02-30') BETWEEN START_DATE AND END_DATE ``` --- ### 五、预防措施 1. **前端验证**:在应用程序层添加日期格式校验 2. **数据库约束**:添加CHECK约束 ```sql ALTER TABLE orders ADD CONSTRAINT chk_date CHECK (order_date IS DATE) ``` 3. **参数化查询**:使用`PreparedStatement`代替字符串拼接 --- ### 六、扩展知识 - **时区问题**:使用`TIMESTAMP WITH TIME ZONE`类型处理跨时区数据 ```sql SELECT CURRENT TIMEZONE FROM SYSIBM.SYSDUMMY1 -- 查看当前时区 ``` - **格式兼容性**:通过`CURRENT DATETIME FORMAT`参数调整默认格式 可通过以下测试验证修正效果: ```sql -- 正确转换示例 VALUES ( TO_DATE(SUBSTR('Report_20240521', 8, 8), 'YYYYMMDD'), TIMESTAMP_FORMAT(REVERSE(SUBSTR(REVERSE('log_20240521143045'),1,14)), 'YYYYMMDDHH24MISS') ) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值