How to do DB migration from id to uuid? - ruby-on-rails

I have table called charges which has fk of prev_charge_id
We have created new column prev_charge_uuid now want to convert prev_charge_id to prev_charge_uuid, what will be the efficient way to do it
DB columns
id name prev_charge_id prev_charge_uuid uuid
1 kv null null abcd-abcd-abcd-abcd
2 Op 1 null qbcd-aqcd-qbcd-qbcd
Have table like this
want prev_charge_uuid to get updated based on prev_charge_id
id name prev_charge_id prev_charge_uuid uuid
1 kv null null abcd-abcd-abcd-abcd
2 Op 1 abcd-abcd-abcd-abcd qbcd-aqcd-qbcd-qbcd

To do what you are requesting is not a good idea. It violates the database design principle that data should be represented in exactly one place. In your example, you could run into problems if a uuid gets changed, but the prev_charge_uuid does not.
A much better strategy is to define the method in the model:
def prev_charge_uuid
self.class.find(prev_charge_id).uuid
end
[update] I just noticed that prev_charge_id is a column in the table, so you can just use it iso calculating previous id... solves the problem that #sergio points out when there are "holes" in the id sequence.

Related

How to auto increment in sqlite database iOS objective c

[Table creation in sqlite manager]i am working on iOS objective c.In my project am using the sqlite manager for database purpose.I declared id is auto increment on the time of table creation of sqlite manager but whenever i execute my code on that time id is not autoincremted.
So decided to wrote the code for auto increment.
I wrote the code for id auto increment but it is not working properly.
Can any please suggest me which code is better for autoincrment.[this is the my database table creation in sqlite manager[Code for id auto increment][Table creation in sqlite manager]code for id creation
Code for table creation in sqlite manager
You should define the field as INTEGER PRIMARY KEY AUTOINCREMENT, but when you insert data, do not include this field in the values being inserted. Don't try to increment this yourself. Let the database do this for you. If, after inserting the record, you want to know what the value assigned was, then call sqlite3_last_insert_rowid.
You might want to declare the id as Primary Key. Please see this answer
create table query
CREATE TABLE COMPANY(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL
);
query to insert
INSERT INTO COMPANY (NAME,AGE,ADDRESS,SALARY) VALUES ( 'Paul', 32, 'California', 20000.00 );
INSERT INTO COMPANY (NAME,AGE,ADDRESS,SALARY) VALUES ('Allen', 25, 'Texas', 15000.00 );
result
ID NAME AGE ADDRESS SALARY
---------- ---------- ---------- ---------- ----------
1 Paul 32 California 20000.0
2 Allen 25 Texas 15000.0

Regenerate ids of existing records

I have a Rails app with a custom algorithm for id generation for one table. Now I decided to use default incremental ids generated by Postgres as primary keys and move my custom values from id to another column like uid. And I want to regenerate values in id column for all records - as normal from 1 to n.
What is the best way to do this? I have about 1000 records. Records from other tables are associated with these records.
You can keep whatever value is in ID column but create a new column named UID and set it as a primary key and auto increment
def self.up
execute "ALTER TABLE mytable modify COLUMN uid int(8) AUTO_INCREMENT"
end
You can tell your model to use UID as primary key as
self.primary_key = 'uid'
You can simply do it by iterating on your records, and updating them (and their associated objects). 1000 records is not that much to process.
Let's say that you have a table named "my_objects", with its model named "MyObject". Let's also say that you have another table, named "related_objects" and its model "RelatedObject"
You can iterate on all your MyObjects records, and update their related objects and the record itself at the same time.
records = MyObject.all #Whatever "MyObject" you have.
i = 0
records.each do |record|
#Updating whatever associated objects the record have
record.related_objects.each do |related_object|
related_object.update_column("my_object_id", i)
end
#Updating the record itself
record.update_column("id", i)
i++
end

Base value in column on id but constrained to not-null

I want to generate a value in a column based on the database ID ActiveRecord assigns to my record. Normally, I would just add an after save callback where this value is generated and than saved to the database.
Unfortunately, I have to deal with a not-null constraint on that column, so it needs to be assigned at the same time when I get an ID. Is there a thread-safe way, to combine both?
You could write your code in transaction block, where you first find the maximum value of id column in the given table and than use that ID value to generate value of other column. Will that work for you?
ActiveRecord::Base.transaction do
id = maximum(:id)
other_column = "#{id} some string"
create(other_column: other_column)
end

Change Data Capture with table joins in ETL

In my ETL process I am using Change Data Capture (CDC) to discover only rows that have been changed in the source tables since the last extraction. Then I do the transformation only for this rows. The problem is when I have for example 2 tables which I want to join into one dimension, and only one of them has changed. For example I have table Countries and Towns as following:
Countries:
ID Name
1 France
Towns:
ID Name Country_ID
1 Lyon 1
Now lets say a new row is added to Towns table:
ID Name Country_ID
1 Lyon 1
2 Paris 2
The Countries table has not been changed, so CDC for these tables shows me only the row from Towns table. The problem is when I do the join between Countries and Towns, there is no row in Countries change set, so the join will result in empty set.
Do you have an idea how to solve it? Of course there might be more difficult cases, involving 3 and more tables, and consequential joins.
This is a typical problem found when doing Realtime Change-Data-Capture, or even Incremental-only daily changes.
There's multiple ways to solve this.
One way would be to do your joins on the natural keys in the dimension or mapping table, to get the associated country (SELECT distinct country_name, [..other attributes..] from dim_table where country_id = X).
Another alternative would be to do the join as part of the change capture process - when a row is loaded to towns, a trigger goes off that loads the foreign key values into the associated staging tables (country, etc).
There is allot i could babble on for more information on but i will be specific to what is in your question. I would suggest the following to get the results...
1st Pass is where everything matches via the join...
Union All
2nd Pass Gets all towns where there isn't a country
(left outer join with a where condition that
requires the ID in the countries table to be null/missing).
You would default the Country ID value in that unmatched join to something designated as a "Unmatched Value" typically 0 or -1 is used or a series of standard -negative numbers that you could assign descriptions to later to identify why data is bad for your example -1 could be "Found Town Without Country".

Reset the id field in a table in a sqlite db in Rails

Im using sqlite db in a sample rails application. From my users table, i have cleared all records using User.delete_all. But now whenever i insert a new record in the table using User.create, the id is starting at a value which is one more than the id of the last record which was there in the table. For example, if my table had 5 records and i cleared all, then when i do User.create, its starting at id 6.
Is there any way i can make the id start from 1 again ?
Thank You
Similar question : How to reset a single table in rails? . We can run the following at rails console to reset id column to 1 for a sqlite table
ActiveRecord::Base.connection.execute("DELETE from sqlite_sequence where name = '<table_name>'")
You seem to have autoincrement turned on for the id column.
Sqlite handles these values in an internal table called sqlite_sequence. You could reset the id for a particular autoincrement-enabled table by querying:
UPDATE "sqlite_sequence" SET "seq" = 0 WHERE "name" = $YOURTABLENAME
However, this is not a good idea because the autoincrement functionality is intended to be used in a way that the user does not influence its algorithm. Ideally, you should not care about the actual value of your id but consider it only as a unique identifier for a record.

Resources