I have a question regarding the design of two tables.
Table 1: The main table, called Batch. Values are added here from parsing files.
Table 2: This table works like a log table, every row that is deleted from table 1 goes here.
Example
Table 1
ID text
1 'bla1'
2 'bla2'
3 'bla3'
Delete row where id is 2 and 3
Table 2
ID text
2 'bla2'
3 'bla3'
Problem:
What if I insert ID 2 and 3 again in table 1 and deletes it? Table 2 would have same data. How can I fix this? Should I just make ID also identity column? So when I add 2 records it would be this (additional question how do I keep counting if I delete the whole table 1?):
Table 1
ID
4 'Bla3'
5 'Bla4'
Just have a unique identifier for Table 1. This identifier should be unique to this table, not for the data you load. You can then load id 100 from your source file as many times as you want, they should get a unique identifier in the Table 1.
An Identity Column seems to fit your requirements for this. I'd look into more audit data as well, perhaps store what file it came from, when it was loaded, who loaded it, etc.
As for filling the log table, you can just attach a trigger on your Table 1 that fills Table 2 with deleted rows, should be pretty straight forward.
It seems that in your design Table 1 uses a surrogate key. In this case you should define also a natural key for your purpose. Then Table 2 will contains natural key and values of Table 1 erased data.
Because you can erase some data for several times, you should add a timestamp field you your table 2.
create table table1 (
id int identity primary key,
[text] varchar(50) not null unique,
... other data ...
)
create table table2 (
[text] varchar(50) not null,
erased datetime not null,
... other data ...
constraint table2_pk
primary key ( [text], erased )
)
Related
Suppose I have a database with 3 tables of rooms: room_lvl1, room_lvl2, room_lvl3 which represent 3 levels in a building. Each level has 20++ rooms. So each table of room has 20++ rows that represent the rooms in that level.
I have a need to delete all attributes in the table except the primary key which is the room number or update everything to a null value except the primary key.
Is there any query I could possibly run?
You can set values to NULL by doing:
update room_lvl1
set col1 = NULL,
col2 = NULL,
. . .;
Where col1 etc are the non-primary key columns.
That seems like a really strange thing to want to do. You could empty the tables:
truncate table room_lvl1;
That would remove all rows.
You could save, truncate, and re-insert:
create table temp_room_lvl1 as select * from room_lvl1;
truncate table room_lvl1;
insert into room_lvl1(pk)
select pk from temp_room_lvl1;
How do you set up a valid auto-incrementing integer primary key on a table if you want to join it with separate files? I get data like this on a daily basis:
Interaction data:
Date | PersonID | DateTime | CustomerID | Other values...
The primary key there would be PersonID + DateTime + CustomerID. If I have an integer key, how can I get that to relate back to another table? I want to know the rows where a specific person interacted with a specific customer so I can tie back those pieces of data together into one master-file.
Survey return data:
Date | PersonID | DateTime | CustomerID | Other values...
I am normally processing all raw data first in pandas before loading it into a database. Some other files also do not have a datetime stamp and only have a date. It is rare for one person to interact with the same customer on the same day so I normally drop all rows where there are duplicates (all instances) so my sample of joins are just purely unique.
Other Data:
Date | PersonID | CustomerID | Other values...
I can't imagine how I can set it up so I know row 56,547 on 'Interaction Data' table matches with row 10,982 on 'Survey Return Data' table. Or should I keep doing it the way I am with a composite key of three columns?
(I'm assuming postgresql since you have tag-spammed this post; it's up to you to translate for other database systems).
It sounds like you're loading data with a complex natural key like (PersonID,DateTime,CustomerID) and you don't want to use the natural key in related tables, perhaps for storage space reasons.
If so, for your secondary tables you might want to CREATE UNLOGGED TABLE a table matching the original input data. COPY the data into that table. Then do an INSERT INTO ... SELECT ... into the final target table, joining on the table with the natural key mapping.
In your case, for example, you'd have table interaction:
CREATE TABLE interaction (
interaction_id serial primary key,
"PersonID" integer
"DateTime" timestamp,
"CustomerID" integer,
UNIQUE("PersonID", "DateTime", "CustomerID"),
...
);
and for table survey_return just a reference to interaction_id:
CREATE TABLE survey_return (
survey_return_id serial primary key,
interaction_id integer not null foreign key references interaction(interaction_id),
col1 integer, -- data cols
..
);
Now create:
CREATE UNLOGGED TABLE survey_return_load (
"PersonID" integer
"DateTime" timestamp,
"CustomerID" integer,
PRIMARY KEY ("PersonID","DateTime", "CustomerID")
col1 integer, -- data cols
...
);
and COPY your data into it, then do an INSERT INTO ... SELECT ... to join the loaded data against the interaction table and insert the result with the derived interaction_id instead of the original natural keys:
INSERT INTO survey_return
SELECT interaction_id, col1, ...
FROM survey_return_load l
LEFT JOIN interaction i ON ( (i."PersonID", i."DateTime", i."CustomerID") = (l."PersonID", l."DateTime", l."CustomerID") );
This will fail with a null violation if there are natural key tuples in the input survey returns that do not appear in the interaction table.
There are always many ways. Here might be one.
A potential customer (table: cust) walking into a car dealership and test driving 3 cars (table: car). An intersection/junction table between cust and car in table cust_car.
3 tables. Each with int autoinc.
Read this answer I wrote up for someone. Happy to work your tables if you need help.
SQL result table, match in second table SET type
That question had nothing to do with yours. But the solution is the same.
I have a table called users with the following columns:
| id | name |
Then another table called images which looks like this:
| id | fileName |
What is the best way to assign a dynamic number of image rows to a to multiple user rows.
You need to add a foreign key to your images table. For example, change your images table to have three columns:
| id | fileName | userID |
This userID must be one of the id values that already exists in the users table, otherwise this column would be pointless. This column will point back to the users table and essentially assigns each image to a specific user. Since one user can have many paintings, we call this a one-to-many relationship.
If you already have the tables created, you can try and run the following query:
ALTER TABLE images ADD userID INT NOT NULL DEFAULT 0;
ALTER TABLE images ADD CONSTRAINT fk_user FOREIGN KEY (userID) REFERENCES users(id);
The first line will add the column, while the second line makes the constraint for it. The constraint ensures that new rows added to the images table MUST have a valid userID. If you try and add a row with a userID that does not exist, you will get an error (and rightfully so, because images shouldn't belong to imaginary users).
This will also set the userID column of all existing image rows to 0. You may want to change this later, but that depends on your individual case.
Hello is it possible to save the deleted auto incremented primary key in my database. For example
I have
Name_ID
1
2
3
4
If I delete primary key 4 and I insert again the primary key of I inserted should be four.
so. Name 1 2 3 4 5
I deleted primary key 5 (Name 1 2 3 4)
I added a data primary key should be 5 again not 6. THANKS!
Auto generated fields always have gaps in these cases.
What if you have an audit or history table that stored the rows with ID = 4, ID = 5? Then delete them again? How do you differentiate rows?
In your example, you've only deleted the last row? What is you delete ID = 1? Then what?
That is, they are just internal numbers unique to that table (and any associated tables like audit ones): no external meaning should be attached
As with other comments and answers here, I would not recommend this, especially if the data in the auto increment column is referenced externally, but you can set the next auto increment number to a specific value via an ALTER TABLE query
ALTER TABLE T_YourTable AUTO_INCREMENT=4
You could also drop the column and then re-add the column with the same attributes (this could be expensive if you have a lot of rows).
Why?
It's only intended to be a unique identifier.
You'll also get gaps with database clusters and whenever you rollback an insert transaction which overlaps a commited transaction - not just when you delete data.
A mechanism to fill-in-the-gaps would be complex, slow and difficult to maintain - and it's not needed.
I have a table that have two fields.
table test
{
fname char(20),
id int not null auto_increment,
primary key(id)
}
now I add 3 records to the table like below:
insert into test(fname) values
('a'),('b'),('c');
and the table looks like
fname id
a 1
b 2
c 3
now I delete b from table so I have:
fname id
a 1
b 3
now again I insert a new record into the table
insert into test(fname) values('d);
and get:
fname id
a 1
b 3
d 4
but I want last record's id to be "2"
how can I do this?
An auto increment column would be used to identify your rows as unique if you have no other candidate for a primary key. If you are relying on their being no gaps in your sequence then you have trouble with the logic of how you are approching the problem, your queries should not rely on anything other than them being unique.
Also find a piece of MySQL Cookbook chapter that says the same
I don't think you can change that. This is houw auto_increment works in mysql.
You can't do that with autoincrement. It only keeps the id of the last inserted record and increments it when you insert. It doesn't keep track of delete operations.
Anyway, why do you want to do it?