PostgreSQL遍历所有的表并设置id为自增主键
这里写自定义目录标题
DO $$
DECLARE
table_info RECORD;
max_id BIGINT;
sequence_name TEXT;
schema_name TEXT := ‘ocean’;
error_message TEXT;
is_identity BOOLEAN;
BEGIN
FOR table_info IN (
SELECT c.table_name, c.column_name
FROM information_schema.columns c
WHERE c.column_name = ‘id’ AND c.table_schema = schema_name
)
LOOP
BEGIN
– 1. 查询当前表的最大 id
EXECUTE FORMAT(‘SELECT COALESCE(MAX(%I), 0) FROM %I.%I’,
table_info.column_name,
schema_name,
table_info.table_name
) INTO max_id;
-- 2. 检查 id 列是否为 IDENTITY 类型EXECUTE FORMAT('SELECT EXISTS (SELECT 1 FROM pg_attribute aJOIN pg_class t ON a.attrelid = t.oidJOIN pg_namespace n ON t.relnamespace = n.oidWHERE n.nspname = %L AND t.relname = %L AND a.attname = %L AND a.attidentity <> '''')',schema_name,table_info.table_name,table_info.column_name) INTO is_identity;IF is_identity THEN-- 3. 如果是 IDENTITY 列,使用专用语法重置RAISE NOTICE 'Table: %I.%I is an IDENTITY column. Resetting...', schema_name, table_info.table_name;EXECUTE FORMAT('ALTER TABLE %I.%I ALTER COLUMN %I RESTART WITH %s',schema_name,table_info.table_name,table_info.column_name,max_id + 1);ELSE-- 4. 如果是普通列(可能使用 SERIAL 或手动序列),执行原逻辑RAISE NOTICE 'Table: %I.%I uses a regular sequence. Processing...', schema_name, table_info.table_name;sequence_name := schema_name || '.' || table_info.table_name || '_' || table_info.column_name || '_seq';-- 检查序列是否存在PERFORM 1FROM pg_class cJOIN pg_namespace n ON n.oid = c.relnamespaceWHERE c.relkind = 'S' AND c.relname = table_info.table_name || '_' || table_info.column_name || '_seq'AND n.nspname = schema_name;IF FOUND THEN-- 序列存在,设置其值EXECUTE FORMAT('SELECT setval(%L, %s)', sequence_name, max_id + 1);ELSE-- 序列不存在,创建并关联EXECUTE FORMAT('CREATE SEQUENCE %I.%I START WITH %s',schema_name,table_info.table_name || '_' || table_info.column_name || '_seq',max_id + 1);-- 检查并设置默认值PERFORM 1FROM information_schema.columnsWHERE table_schema = schema_nameAND table_name = table_info.table_nameAND column_name = table_info.column_nameAND column_default IS NULL;IF FOUND THENEXECUTE FORMAT('ALTER TABLE %I.%I ALTER COLUMN %I SET DEFAULT nextval(%L)',schema_name,table_info.table_name,table_info.column_name,sequence_name);END IF;END IF;END IF;-- 5. 统一检查并设置主键(两种类型都适用)PERFORM 1FROM information_schema.table_constraintsWHERE table_schema = schema_nameAND table_name = table_info.table_nameAND constraint_type = 'PRIMARY KEY';IF NOT FOUND THENRAISE NOTICE 'Setting PRIMARY KEY for table: %I.%I', schema_name, table_info.table_name;EXECUTE FORMAT('ALTER TABLE %I.%I ADD PRIMARY KEY (%I)',schema_name,table_info.table_name,table_info.column_name);END IF;RAISE NOTICE 'Successfully processed table: %I.%I', schema_name, table_info.table_name;EXCEPTIONWHEN OTHERS THENGET STACKED DIAGNOSTICS error_message = MESSAGE_TEXT;RAISE NOTICE 'Error processing table %I.%I: %', schema_name, table_info.table_name, error_message;
END;
END LOOP;
END
$$;
