B
B
BonBon Slick2018-11-09 17:11:48
PostgreSQL
BonBon Slick, 2018-11-09 17:11:48

Replacing int primary key with UUID without losing links?

Mistakes that may occur and their best solution?

Datatype mismatch: 7 ERROR:  column "id" cannot be cast automatically to type uuid  
  HINT:  You might need to specify "USING id::uuid".   
         
// ... лучше не апдейтить рут юзера в миграции

Insufficient privilege: 7 ERROR:  permission denied to create extension "uuid-ossp"  
  HINT:  Must be superuser to create this extension. 

// ...

 SQLSTATE[42846]: Cannot coerce: 7 ERROR:  cannot cast type integer to uuid  
  LINE 1: ...user" ALTER COLUMN "id" SET DATA TYPE UUID USING "id"::UUID;

You can just drive in one of the ways
$this->addSql('ALTER TABLE "user" ALTER COLUMN id SET DATA TYPE UUID USING (uuid_generate_v4());');
       $this->addSql('ALTER TABLE "user" ALTER COLUMN "id" SET DATA TYPE UUID USING "id"::UUID;');
       $this->addSql('ALTER TABLE "user" ALTER COLUMN "id" SET DATA TYPE UUID USING LPAD(TO_HEX(id), 32, \'0\')::UUID;');

Or directly recreate the column
$this->addSql('ALTER TABLE "user" ADD COLUMN new_id UUID NULL');
        $this->addSql('UPDATE "user" SET new_id = CAST(LPAD(TO_HEX(id), 32, \'0\') AS UUID)');
        $this->addSql('ALTER TABLE "user" DROP COLUMN id cascade');
        $this->addSql('ALTER TABLE "user" RENAME COLUMN new_id TO id');
        $this->addSql('ALTER TABLE "user" ALTER COLUMN id SET NOT NULL');

That's just everything described above, kills connections, old Int keys remain everywhere. I would not want to manually parve each table that depends on the user id, there are too many tables and data.
It should be borne in mind that extensions are required for functions. And they, in turn, create even more overhead calculations if there is a lot of data. It is unlikely that everything will fit into one commit, and breaking it into many small ones can damage some of the data and leave the other as it was, and the Integrity will be broken.
In my example, Symfony 4 and Doctrine 2.6
were used.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Melkij, 2018-11-09
@BonBonSlick

Correct - use int. Or bigint if there is not enough bit depth of int. And don't use uuid. The reason for this is the random distribution of uuid, which completely knocks down the scheduler statistics, noticeably inflates indexes, and also the fact that a 128-bit uuid is not a simple data type, which affects the performance of operations around it.
Well, if you really want to, then you listed the ways to change one column yourself. Further, there are more complex ways to reduce the downtime of the migration time.
And you must update all related data yourself, the multi-table update syntax will help. The foreign key mechanism will directly prohibit you from changing the type or deleting the column. And if you do not have a foreign key, then you have no connections from the point of view of the database.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question