热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
本提示词专门为开发者和数据库管理员设计,能够根据不同的数据库系统和迁移需求,自动生成高质量的数据迁移脚本。通过分析源数据库类型、目标数据库类型和数据结构特征,系统会生成确保数据完整性、最小化停机时间并简化复杂迁移任务的定制化脚本。该提示词支持主流数据库系统间的迁移,具备智能数据类型映射、约束条件处理和性能优化建议等功能,大幅提升数据库迁移工作的效率和可靠性。
本方案面向“MySQL → PostgreSQL”的标准复杂度迁移,核心特点:
说明:由于未提供具体表结构,脚本包含可复用的迁移过程、函数与两个示例表(customers、orders)。你可按示例快速替换实际表名与列映射表达式完成迁移。
常见 MySQL → PostgreSQL 类型映射与注意项:
数值
字符与二进制
日期与时间
结构化类型
空间类型
其他
以下脚本在 PostgreSQL 上执行(psql),需预先安装 mysql_fdw(PostgreSQL 扩展)。将其中的连接信息与示例表替换为你的实际环境。脚本按步骤组织,可分批执行。
-- =========================================
-- 环境与FDW准备
-- =========================================
BEGIN;
-- 1) 创建FDW扩展(确保已安装:CREATE EXTENSION IF NOT EXISTS mysql_fdw;)
CREATE EXTENSION IF NOT EXISTS mysql_fdw;
-- 2) 目标与源schema
CREATE SCHEMA IF NOT EXISTS src_mysql; -- 用于承载MySQL的外部表
CREATE SCHEMA IF NOT EXISTS tgt; -- 目标PostgreSQL表schema(可改为public)
-- 3) 定义MySQL连接(替换为你的配置)
-- 注意:避免将密码明文提交到版本库;生产环境使用安全凭据管理
DROP SERVER IF EXISTS mysql_src CASCADE;
CREATE SERVER mysql_src
FOREIGN DATA WRAPPER mysql_fdw
OPTIONS (host 'MYSQL_HOST', port '3306');
CREATE USER MAPPING FOR CURRENT_USER
SERVER mysql_src
OPTIONS (username 'MYSQL_USER', password 'MYSQL_PASSWORD');
COMMIT;
-- 4) 导入源数据库表为外部表(替换数据库名与需要的表,或全量导入后按需过滤)
-- 注:部分版本的mysql_fdw支持IMPORT FOREIGN SCHEMA,若不支持需手工CREATE FOREIGN TABLE。
-- 下面尝试导入名为 source_db 的MySQL数据库的所有表至 src_mysql schema。
DO $$
BEGIN
BEGIN
EXECUTE $sql$
IMPORT FOREIGN SCHEMA `source_db`
FROM SERVER mysql_src
INTO src_mysql
$sql$;
EXCEPTION WHEN others THEN
RAISE NOTICE 'IMPORT FOREIGN SCHEMA 不可用或失败,请使用手工 CREATE FOREIGN TABLE 方式.';
END;
END $$;
-- 如IMPORT不支持,请按以下模板手工创建外部表:
-- CREATE FOREIGN TABLE src_mysql.customers (
-- id integer,
-- name varchar(255),
-- is_active smallint,
-- created_at timestamp without time zone
-- ) SERVER mysql_src OPTIONS (dbname 'source_db', table_name 'customers');
-- =========================================
-- 通用转换与校验函数
-- =========================================
-- 修复MySQL零日期('0000-00-00' / '0000-00-00 00:00:00')
CREATE OR REPLACE FUNCTION tgt.safe_date(d text)
RETURNS date LANGUAGE sql IMMUTABLE AS $$
SELECT CASE WHEN d IS NULL OR d='0000-00-00' THEN NULL ELSE d::date END
$$;
CREATE OR REPLACE FUNCTION tgt.safe_timestamp(d text)
RETURNS timestamp without time zone LANGUAGE sql IMMUTABLE AS $$
SELECT CASE WHEN d IS NULL OR d='0000-00-00 00:00:00' THEN NULL ELSE d::timestamp WITHOUT TIME ZONE END
$$;
-- TINYINT(1) → boolean
CREATE OR REPLACE FUNCTION tgt.tinyint_to_bool(i integer)
RETURNS boolean LANGUAGE sql IMMUTABLE AS $$
SELECT CASE WHEN i IS NULL THEN NULL WHEN i=0 THEN FALSE ELSE TRUE END
$$;
-- BINARY(16)/CHAR(36) → uuid(示例:若源为BINARY(16)存储UUID)
CREATE OR REPLACE FUNCTION tgt.bytes_to_uuid(b bytea)
RETURNS uuid LANGUAGE plpgsql IMMUTABLE AS $$
DECLARE
v uuid;
BEGIN
IF b IS NULL OR length(b) <> 16 THEN
RETURN NULL;
END IF;
-- 将16字节转UUID(以big-endian为例,如有自定义字节序需调整)
SELECT (
encode(substr(b,1,4),'hex')||'-'||
encode(substr(b,5,2),'hex')||'-'||
encode(substr(b,7,2),'hex')||'-'||
encode(substr(b,9,2),'hex')||'-'||
encode(substr(b,11,6),'hex')
)::uuid INTO v;
RETURN v;
END $$;
-- 通用表校验和(按主键排序,将整行转JSON后聚合md5)
-- 注意:若迁移时有类型归一化(如tinyint→boolean),源/目标校验和可能不同;此函数用于同构比较或目标内复核。
CREATE OR REPLACE FUNCTION tgt.table_checksum(_schema text, _table text, _pk text)
RETURNS text LANGUAGE plpgsql AS $$
DECLARE out_md5 text;
BEGIN
EXECUTE format($fmt$
SELECT md5(string_agg(md5(row_to_json(t)::text), ''))
FROM (SELECT * FROM %I.%I ORDER BY %I) t
$fmt$, _schema, _table, _pk)
INTO out_md5;
RETURN out_md5;
EXCEPTION WHEN undefined_table THEN
RETURN NULL;
END $$;
-- 通用迁移过程(结构创建、数据导入、索引约束与校验)
CREATE OR REPLACE PROCEDURE tgt.migrate_table(
src_schema text,
src_table text,
dst_schema text,
dst_table text,
dst_ddl text, -- 目标表DDL(CREATE TABLE ...)
insert_select text, -- 数据加载语句(INSERT INTO ... SELECT ... FROM src_schema.src_table)
pk_col text, -- 主键列名(用于序列/标识重置与排序校验)
create_indexes text DEFAULT NULL, -- 可选,索引DDL(可为多个语句串)
create_constraints text DEFAULT NULL -- 可选,约束DDL(FK/UNIQUE/CHECK等)
)
LANGUAGE plpgsql
AS $$
DECLARE
next_start bigint;
src_cnt bigint;
dst_cnt bigint;
BEGIN
-- 1) 创建目标表
EXECUTE dst_ddl;
-- 2) 数据加载(建议在单独事务中批量导入)
EXECUTE insert_select;
-- 3) 重置标识列起始值(若使用IDENTITY)
IF pk_col IS NOT NULL THEN
EXECUTE format('SELECT COALESCE(MAX(%I),0)+1 FROM %I.%I', pk_col, dst_schema, dst_table) INTO next_start;
-- 对IDENTITY列生效
EXECUTE format('ALTER TABLE %I.%I ALTER COLUMN %I RESTART WITH %s', dst_schema, dst_table, pk_col, next_start);
END IF;
-- 4) 创建索引(如有)
IF create_indexes IS NOT NULL THEN
EXECUTE create_indexes;
END IF;
-- 5) 创建约束(如有;建议使用 DEFERRABLE INITIALLY DEFERRED)
IF create_constraints IS NOT NULL THEN
EXECUTE create_constraints;
END IF;
-- 6) 验证行数一致性
EXECUTE format('SELECT COUNT(*) FROM %I.%I', src_schema, src_table) INTO src_cnt;
EXECUTE format('SELECT COUNT(*) FROM %I.%I', dst_schema, dst_table) INTO dst_cnt;
IF src_cnt <> dst_cnt THEN
RAISE EXCEPTION '行数不一致:源=%, 目标=%(表:%.%→%.%)', src_cnt, dst_cnt, src_schema, src_table, dst_schema, dst_table;
END IF;
-- 注:类型归一化会导致跨库校验和不一致,这里不做跨库校验和比对。
RAISE NOTICE '迁移完成:%.% → %.%(行数=%)', src_schema, src_table, dst_schema, dst_table, dst_cnt;
END $$;
-- =========================================
-- 示例:customers 表迁移(按需替换)
-- 源MySQL:customers(id INT AUTO_INCREMENT PK, name VARCHAR(255), is_active TINYINT(1), created_at DATETIME)
-- =========================================
-- 目标表DDL(注意使用IDENTITY以替代AUTO_INCREMENT)
DO $$
DECLARE
ddl text := $DDL$
CREATE TABLE IF NOT EXISTS tgt.customers (
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name varchar(255) NOT NULL,
is_active boolean NOT NULL DEFAULT TRUE,
created_at timestamp without time zone
)
$DDL$;
ins text := $INS$
INSERT INTO tgt.customers (id, name, is_active, created_at)
SELECT
c.id,
c.name,
tgt.tinyint_to_bool(c.is_active) AS is_active,
tgt.safe_timestamp(c.created_at::text) AS created_at
FROM src_mysql.customers c
$INS$;
idx text := $IDX$
CREATE INDEX IF NOT EXISTS idx_customers_name ON tgt.customers(name);
$IDX$;
BEGIN
CALL tgt.migrate_table(
'src_mysql','customers',
'tgt','customers',
ddl, ins, 'id',
idx, NULL
);
END $$;
-- =========================================
-- 示例:orders 表迁移(含ENUM映射为text + CHECK,FK约束)
-- 源MySQL:orders(id BIGINT AUTO_INCREMENT PK, customer_id INT, amount DECIMAL(12,2), status ENUM('pending','paid','cancelled'), order_date DATE)
-- =========================================
DO $$
DECLARE
ddl text := $DDL$
CREATE TABLE IF NOT EXISTS tgt.orders (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
customer_id integer NOT NULL,
amount numeric(12,2) NOT NULL,
status text NOT NULL,
order_date date,
CHECK (status IN ('pending','paid','cancelled'))
)
$DDL$;
ins text := $INS$
INSERT INTO tgt.orders (id, customer_id, amount, status, order_date)
SELECT
o.id,
o.customer_id,
o.amount::numeric(12,2),
o.status::text,
tgt.safe_date(o.order_date::text)
FROM src_mysql.orders o
$INS$;
idx text := $IDX$
CREATE INDEX IF NOT EXISTS idx_orders_customer_id ON tgt.orders(customer_id);
$IDX$;
cons text := $CONS$
ALTER TABLE tgt.orders
ADD CONSTRAINT fk_orders_customer
FOREIGN KEY (customer_id) REFERENCES tgt.customers(id)
DEFERRABLE INITIALLY DEFERRED;
$CONS$;
BEGIN
CALL tgt.migrate_table(
'src_mysql','orders',
'tgt','orders',
ddl, ins, 'id',
idx, cons
);
END $$;
-- =========================================
-- 其它表:请参考以上模式,每表一段 DO 块,填充目标DDL与INSERT..SELECT转换表达式。
-- =========================================
-- 可选:迁移后统计与分析
ANALYZE tgt.customers;
ANALYZE tgt.orders;
-- 结束
前置准备
连接配置
结构设计
数据迁移
验证与优化
切换与回滚
如需针对你的实际表结构生成精确的 DDL 与 INSERT..SELECT 转换表达式,请提供 MySQL 表的 CREATE TABLE 语句或信息架构(字段名、类型、约束),我可进一步输出定制化的完整迁移脚本。
本方案面向 Oracle 到 MySQL 的复杂迁移场景,兼顾数据类型精确映射、主键与序列替换、约束与索引重建、批量高效数据导入以及数据一致性验证。整体策略如下:
说明:尽量保持与 Oracle 精度一致;MySQL 版本建议为 8.0.16+(支持 CHECK)。
注意:
以下脚本为通用模板与示例,需根据实际表结构替换对象名、列定义与约束。示例包含典型三张表:customers、orders、order_items,并演示序列替代与批量导入。
-- 建议在全新 Schema 下迁移与验证
CREATE DATABASE IF NOT EXISTS target_mig
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_0900_ai_ci;
USE target_mig;
-- 基本会话配置
SET NAMES utf8mb4;
SET time_zone = '+00:00';
SET sql_mode = 'STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE';
-- 为避免导入期间外键开销,后续导数时临时关闭(见执行步骤)
-- SET FOREIGN_KEY_CHECKS=0;
-- SET UNIQUE_CHECKS=0;
-- customers(Oracle: NUMBER PK + VARCHAR2 + DATE)
CREATE TABLE customers (
customer_id BIGINT NOT NULL, -- Oracle NUMBER(10) 映射
name VARCHAR(200) NOT NULL,
email VARCHAR(320) NULL, -- RFC email 可到 320 字符
created_at DATETIME(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT pk_customers PRIMARY KEY (customer_id),
CONSTRAINT uq_customers_email UNIQUE (email),
CONSTRAINT chk_customers_name CHECK (CHAR_LENGTH(name) > 0)
) ENGINE=InnoDB;
-- orders(Oracle: 序列 + 触发器填充;时间戳与状态检查)
CREATE TABLE orders (
order_id BIGINT NOT NULL,
customer_id BIGINT NOT NULL,
order_date DATETIME(6) NOT NULL,
status VARCHAR(30) NOT NULL, -- Oracle CHECK(status in (...))
total_amt DECIMAL(18,2) NOT NULL DEFAULT 0,
CONSTRAINT pk_orders PRIMARY KEY (order_id),
INDEX idx_orders_customer_id (customer_id)
) ENGINE=InnoDB;
-- order_items(含数量与价格,注意精度)
CREATE TABLE order_items (
item_id BIGINT NOT NULL,
order_id BIGINT NOT NULL,
product_code VARCHAR(64) NOT NULL,
quantity DECIMAL(18,6) NOT NULL, -- Oracle NUMBER(18,6)
unit_price DECIMAL(18,2) NOT NULL,
CONSTRAINT pk_order_items PRIMARY KEY (item_id),
INDEX idx_order_items_order_id (order_id)
) ENGINE=InnoDB;
-- 外键约束
ALTER TABLE orders
ADD CONSTRAINT fk_orders_customer
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE order_items
ADD CONSTRAINT fk_items_order
FOREIGN KEY (order_id) REFERENCES orders(order_id)
ON DELETE CASCADE ON UPDATE RESTRICT;
-- 示例状态检查(MySQL 8.0.16+)
ALTER TABLE orders
ADD CONSTRAINT chk_orders_status
CHECK (status IN ('CREATED','PAID','SHIPPED','CANCELLED'));
A. 将主键列改为 AUTO_INCREMENT(仅当序列不跨表共享)
ALTER TABLE customers MODIFY customer_id BIGINT NOT NULL AUTO_INCREMENT;
ALTER TABLE orders MODIFY order_id BIGINT NOT NULL AUTO_INCREMENT;
ALTER TABLE order_items MODIFY item_id BIGINT NOT NULL AUTO_INCREMENT;
说明:导入历史数据时可显式写入主键值,AUTO_INCREMENT 不会阻止。
B. 跨表共享序列(可选):序列表 + 函数
-- 通用序列表
CREATE TABLE sequences (
name VARCHAR(64) NOT NULL PRIMARY KEY,
val BIGINT NOT NULL
) ENGINE=InnoDB;
-- 初始化已有的 Oracle 序列当前值(需从 Oracle 数据字典查询 last_number)
INSERT INTO sequences(name, val) VALUES
('seq_orders', 100000), -- 示例值,替换为实际序列当前值
('seq_items', 500000);
DELIMITER $$
CREATE FUNCTION nextval(seq_name VARCHAR(64))
RETURNS BIGINT
DETERMINISTIC
BEGIN
-- 使用 LAST_INSERT_ID 技巧保证并发安全
UPDATE sequences SET val = LAST_INSERT_ID(val + 1) WHERE name = seq_name;
RETURN LAST_INSERT_ID();
END$$
DELIMITER ;
-- 使用触发器示例(当不使用 AUTO_INCREMENT)
DELIMITER $$
CREATE TRIGGER trg_orders_before_ins
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
IF NEW.order_id IS NULL OR NEW.order_id = 0 THEN
SET NEW.order_id = nextval('seq_orders');
END IF;
END$$
DELIMITER ;
A. Oracle 侧导出(优先 SQLcl)
-- 使用 SQLcl(支持 SET SQLFORMAT)
SET SQLFORMAT csv
SET NLS_DATE_FORMAT 'YYYY-MM-DD"T"HH24:MI:SS'
SET NLS_TIMESTAMP_FORMAT 'YYYY-MM-DD"T"HH24:MI:SS.FF6'
SPOOL customers.csv
SELECT customer_id, name, email, created_at FROM customers ORDER BY customer_id;
SPOOL OFF
SPOOL orders.csv
SELECT order_id, customer_id,
TO_CHAR(order_date, 'YYYY-MM-DD"T"HH24:MI:SS.FF6') AS order_date,
status, total_amt
FROM orders ORDER BY order_id;
SPOOL OFF
SPOOL order_items.csv
SELECT item_id, order_id, product_code, quantity, unit_price
FROM order_items ORDER BY item_id;
SPOOL OFF
若仅有 SQL*Plus,可设置分隔与引号,确保转义与空值一致(略)。
B. MySQL 侧导入(注意 secure_file_priv 设置;如用 LOCAL 需客户端支持)
-- 导入前建议关闭外键与唯一检查,加速导入(执行步骤中再开启)
SET FOREIGN_KEY_CHECKS=0;
SET UNIQUE_CHECKS=0;
SET AUTOCOMMIT=0;
-- customers
LOAD DATA LOCAL INFILE '/path/customers.csv'
INTO TABLE customers
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"'
LINES TERMINATED BY '\n'
(customer_id, @v_name, @v_email, @v_created_at)
SET
name = NULLIF(@v_name, ''),
email = NULLIF(@v_email, ''),
created_at = STR_TO_DATE(@v_created_at, '%Y-%m-%dT%H:%i:%s');
-- orders
LOAD DATA LOCAL INFILE '/path/orders.csv'
INTO TABLE orders
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"'
LINES TERMINATED BY '\n'
(order_id, customer_id, @v_order_date, @v_status, total_amt)
SET
order_date = STR_TO_DATE(@v_order_date, '%Y-%m-%dT%H:%i:%s.%f'),
status = NULLIF(@v_status, '');
-- order_items
LOAD DATA LOCAL INFILE '/path/order_items.csv'
INTO TABLE order_items
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"'
LINES TERMINATED BY '\n'
(item_id, order_id, product_code, quantity, unit_price);
COMMIT;
-- 导入完成后恢复检查
SET FOREIGN_KEY_CHECKS=1;
SET UNIQUE_CHECKS=1;
SET AUTOCOMMIT=1;
-- 示例:已在上文提供 FK/CHK;若为了最大化性能可在此阶段再执行
-- 另外建议为常用查询列添加必要索引(结合执行计划)
CREATE INDEX idx_orders_status_date ON orders(status, order_date);
CREATE INDEX idx_items_product ON order_items(product_code);
-- 示例:将空字符串标准化为 NULL(实际根据业务列选择)
UPDATE customers SET email = NULL WHERE email = '';
准备阶段
架构搭建
数据导出
批量导入
约束与索引重建
验证与优化
切换与回滚
如需将上述模板生成针对您实际的 Oracle 数据字典的完整 MySQL DDL/约束/索引脚本,请提供具体表结构(列名、数据类型、精度、约束、索引、序列与触发器定义),我可按此输出可直接执行的迁移脚本。
本方案针对从 SQL Server 迁移到 PostgreSQL 的“简单”场景,聚焦常见表结构、基本约束和索引的迁移与数据导入。方案特点:
如未提供具体表结构,迁移脚本以模板形式给出,可直接替换占位符后使用。
以下为常见 SQL Server 到 PostgreSQL 的类型映射(简单场景适用):
注意:SQL Server 的大小写不敏感与排序规则(collation)与 PostgreSQL 不同。若需不区分大小写的比较,建议使用 citext 扩展或统一 lower()/upper() 处理。
以下提供 PostgreSQL 端的完整可执行模板脚本(含扩展、Schema、表结构、约束、索引与数据导入)。请根据实际表结构进行替换补充。
-- ================================================
-- PostgreSQL 迁移脚本模板(请在 psql 客户端执行)
-- 适用:简单场景,常规表、约束、索引、CSV 导入
-- ================================================
-- 1) 基础设置与扩展
BEGIN;
-- 建议在新库中执行,避免与现有对象冲突
-- 客户端编码(确保 CSV 为 UTF-8)
SET client_encoding TO 'UTF8';
-- 添加常用扩展(根据需要选择)
-- 若使用 uuid_generate_v4(),需要 uuid-ossp
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- 如需 gen_random_uuid() 可改用 pgcrypto:
-- CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- 如需不区分大小写的文本列(可选)
-- CREATE EXTENSION IF NOT EXISTS "citext";
-- 2) 创建目标 schema(保留 SQL Server 的 dbo 命名习惯)
CREATE SCHEMA IF NOT EXISTS dbo;
-- 3) 示例表结构(请替换为实际表结构)
-- 下面示例涵盖常用类型与约束。将其复制拓展为你的所有表。
-- 示例一:dbo.users
CREATE TABLE IF NOT EXISTS dbo.users (
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
username varchar(100) NOT NULL,
email varchar(255) NOT NULL,
is_active boolean NOT NULL DEFAULT true,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
external_guid uuid DEFAULT uuid_generate_v4(),
-- 如 SQL Server 为 NVARCHAR(MAX),建议用 text
bio text
);
-- 唯一约束(示例)
ALTER TABLE dbo.users
ADD CONSTRAINT uq_users_email UNIQUE (email);
-- 示例二:dbo.orders(含外键、数值类型)
CREATE TABLE IF NOT EXISTS dbo.orders (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
user_id integer NOT NULL,
order_number varchar(50) NOT NULL,
amount numeric(18,2) NOT NULL,
status varchar(20) NOT NULL,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- 示例 BIT → boolean
paid boolean NOT NULL DEFAULT false,
-- 示例 DATETIMEOFFSET → timestamptz(如有)
-- paid_at timestamp with time zone
-- 示例 UNIQUEIDENTIFIER → uuid
source_guid uuid
);
-- 外键约束(设为 DEFERRABLE,便于批量导入时推迟检查)
ALTER TABLE dbo.orders
ADD CONSTRAINT fk_orders_user
FOREIGN KEY (user_id) REFERENCES dbo.users(id)
DEFERRABLE INITIALLY DEFERRED;
-- 唯一索引(示例)
CREATE UNIQUE INDEX IF NOT EXISTS idx_orders_order_number
ON dbo.orders (order_number);
-- 非唯一索引(示例)
CREATE INDEX IF NOT EXISTS idx_orders_user_id_status
ON dbo.orders (user_id, status);
-- 4) 数据导入(推荐使用 \copy 在 psql 客户端执行)
-- 注意:\copy 是 psql 元命令,运行于客户端,避免服务器文件权限问题
-- 将 SQL Server 导出的 CSV 文件路径替换为你的实际路径
-- 导入用户数据
-- CSV 须包含表列的表头,且编码为 UTF-8
\copy dbo.users (id, username, email, is_active, created_at, external_guid, bio)
FROM '/path/to/export/users.csv' WITH (FORMAT csv, HEADER true);
-- 导入订单数据(外键已设为 DEFERRABLE)
\copy dbo.orders (id, user_id, order_number, amount, status, created_at, paid, source_guid)
FROM '/path/to/export/orders.csv' WITH (FORMAT csv, HEADER true);
-- 5) 迁移后检查(示例:确保关键约束生效)
-- 若导入时临时去除 NOT NULL/UNIQUE,需在此处重新启用并清理坏数据
-- 简单场景建议直接在 DDL 中启用约束,避免后置修复
COMMIT;
-- 6) 可选:校验辅助查询(行数、空值、唯一性)
-- 行数
-- SELECT COUNT(*) FROM dbo.users;
-- SELECT COUNT(*) FROM dbo.orders;
-- 唯一性与空值检查
-- SELECT email, COUNT(*) FROM dbo.users GROUP BY email HAVING COUNT(*) > 1;
-- SELECT COUNT(*) FROM dbo.users WHERE email IS NULL;
-- 7) 性能建议(可在数据导入结束后)
-- ANALYZE 更新统计信息
ANALYZE dbo.users;
ANALYZE dbo.orders;
-- 可按需 VACUUM(通常不必立即执行)
-- VACUUM (ANALYZE) dbo.users;
-- VACUUM (ANALYZE) dbo.orders;
说明:
评估与准备
导出表结构
导出数据
在 PostgreSQL 中创建架构
导入数据
校验与优化
切换与回滚预案
行数一致性