简体   繁体   中英

How to convert MySQL's BIGINT into unsigned without losing data?

I need to convert MySQL database tables column from (signed) BIGINT into unsigned BIGINT . If I do:

ALTER TABLE `$tblNm` MODIFY `flgs` BIGINT UNSIGNED;

Any values that have 63-bit set are reset to 0!

What do I need to do so that all values are converted without any loss?

Similar to this

You can also try to add new column with unsigned BIGINT

         ALTER TABLE `$tblNm`
         ADD COLUMN new_column BIGINT UNSIGNED AFTER flgs;

Then update casted values in new column by using cast

        UPDATE `$tblNm` 
        SET new_column=CAST(flgs AS UNSIGNED);

Then drop column flgs

       ALTER TABLE `$tblNm`
       DROP COLUMN flgs;

Rename the new column with flgs

       ALTER TABLE `$tblNm`
       CHANGE COLUMN new_column flgs BIGINT UNSIGNED

EDIT In order to execute this in transactions we can update this as following.

         SET autocommit=0;
         START TRANSACTION;
         ALTER TABLE `$tblNm`
         ADD COLUMN new_column BIGINT UNSIGNED AFTER flgs;
         UPDATE `$tblNm` 
         SET new_column=CAST(flgs AS UNSIGNED);
         ALTER TABLE `$tblNm`
         DROP COLUMN flgs;
         ALTER TABLE `$tblNm`
         CHANGE COLUMN new_column flgs BIGINT UNSIGNED;
         COMMIT;

EDIT-2 If there is need to lock tables before starting transactions, the above script will be changed as

         SET autocommit=0;
         LOCK TABLES `$tblNm` WRITE
         ALTER TABLE `$tblNm`
         ADD COLUMN new_column BIGINT UNSIGNED AFTER flgs;
         UPDATE `$tblNm` 
         SET new_column=CAST(flgs AS UNSIGNED);
         ALTER TABLE `$tblNm`
         DROP COLUMN flgs;
         ALTER TABLE `$tblNm`
         CHANGE COLUMN new_column flgs BIGINT UNSIGNED;
         COMMIT;
         UNLOCK TABLES;

In this case, you dont need to explicitly write START TRANSACTION

As I understand - You have a bitmask stored as BIGINT (signed) and the column contains negative numbers (leftmost bit set to 1). You want to convert the column type to BIGINT UNSIGNED preserving the binary value.

I would suggest to convert the type to BINARY(8) and then to BIGINT UNSIGNED . Unfortunately the second step didn't work. But converting over BIT(64) works in my test. So you can try:

ALTER TABLE tbl MODIFY `flgs` BIT(64);
ALTER TABLE tbl MODIFY `flgs` BIGINT UNSIGNED;

Test case:

create table tbl (flgs bigint);
insert into tbl (flgs) values (1), (-1);

ALTER TABLE tbl MODIFY `flgs` BIT(64);
ALTER TABLE tbl MODIFY `flgs` BIGINT UNSIGNED;

select * from tbl;

Returns:

| flgs                 |
| -------------------- |
| 1                    |
| 18446744073709551615 |

View on DB Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM