嗨,未来的PostgreSQL大神们!今天我们聊聊也许是编程里最有价值的技能之一——避免犯错。当然,所有错误都避免不了,尤其你刚开始学SQL的时候。但快速搞懂常见的坑还是没问题的。这就像在黑暗的房间里走路,四处都是角落:你可能会撞几下,但很快就知道哪里有啥。我来帮你避开创建和修改表时的“尖角”。
错误1:选错数据类型
数据类型的选择就像给锁配钥匙。选错“钥匙”——也就是数据类型,可能导致表用起来不对劲,或者效率很低。
错误示例:
你想建个列来存手机号,习惯性地选了INTEGER类型。听起来挺合理,毕竟号码是数字嘛。但问题是INTEGER不适合存这些数据:
- 以零开头(
0123456789会变成123456789)。 - 包含像“+”或者空格这样的符号。
-- 错误写法:
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
phone_number INTEGER -- 哎呀
);
-- 正确写法:
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
phone_number VARCHAR(15) -- 适合存各种格式的号码
);
怎么避免?
选数据类型前,仔细分析你要存的数据。如果不确定,去看看PostgreSQL官方数据类型文档。
错误2:忽略NOT NULL、CHECK、UNIQUE约束
约束能帮你保证数据的完整性。忘了它们,你的表里就会乱七八糟,比如本不该有空值的地方出现了空值。
错误示例: 你建了个学生表,结果忘了规定名字和年龄是必填的。
-- 错误写法:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
age INTEGER
);
INSERT INTO students (name, age) VALUES (NULL, NULL); -- 这是什么鬼?!
正确写法:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL, -- 名字必填
age INTEGER CHECK (age > 0) -- 年龄必须大于0
);
怎么避免?
必填字段一定要加约束。这就像“安全锁”,能防止脏数据混进来。
错误3:唯一性问题
有时候你会忘了给本该唯一的列加UNIQUE约束,结果数据重复了。
错误示例: 你建了个邮箱地址表,结果忘了加UNIQUE。
-- 错误写法:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(100)
);
INSERT INTO users (email) VALUES ('user@example.com');
INSERT INTO users (email) VALUES ('user@example.com'); -- 这个邮箱已经有了!
正确写法:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(100) UNIQUE -- 邮箱唯一
);
怎么避免?
只要值要唯一,就一定加UNIQUE。想更灵活点,可以用CONSTRAINT给约束起个名字:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(100),
CONSTRAINT unique_email UNIQUE (email)
);
错误4:修改表(ALTER TABLE)时出错
用ALTER TABLE的时候要小心,尤其表里已经有数据了。比如你可能忘了考虑列里的合法值,结果和已有数据冲突。
错误示例: 你想给已经存在的列加NOT NULL,但里面已经有NULL值了。
-- 错误写法:
ALTER TABLE students ALTER COLUMN name SET NOT NULL; -- 报错!
如果表里已经有NULL,PostgreSQL不会让你加这个约束。
怎么办?
加约束前,先保证数据都合规。比如:
UPDATE students SET name = '未知' WHERE name IS NULL;
ALTER TABLE students ALTER COLUMN name SET NOT NULL;
错误5:删除表或数据前没检查
用DROP TABLE删表或用DELETE删数据,这种操作是不可逆的。所以删之前一定要确认你删的是啥。
错误示例:
DROP TABLE courses; -- 哎呀,删错表了!
怎么避免?
在psql里用\dt命令看看有哪些表,确认下再删。
或者用DROP TABLE IF EXISTS,这样删不存在的表也不会报错:
DROP TABLE IF EXISTS courses;
错误6:临时表的坑
临时表在会话结束后就没了。如果你会话结束后还想用临时表,就会报错。
错误示例:
CREATE TEMP TABLE temp_students (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
-- 会话结束后再...
SELECT * FROM temp_students; -- 报错:表没了!
怎么避免?
如果你需要跨会话用临时数据,就用普通表,或者在文档里说明只在一个会话里用。
错误7:测试时忘了加约束
开发时你可能觉得“约束以后再加吧”,但实际情况是“以后”很容易忘。
错误示例:
CREATE TABLE test_table (
id SERIAL PRIMARY KEY,
name VARCHAR(50)
);
-- 插入数据:
INSERT INTO test_table (name) VALUES ('重复名字');
INSERT INTO test_table (name) VALUES ('重复名字'); -- 问题来了...
怎么避免?
哪怕是测试阶段,也要一开始就加好约束:
CREATE TABLE test_table (
id SERIAL PRIMARY KEY,
name VARCHAR(50) UNIQUE -- 省心
);
GO TO FULL VERSION