I have two different tables with multiple columns. Like the following
Table1
ID CUSTOMER PRODUCT DETAILS
21 joe phone
22 doe shoe
23 john cup
Table2
PRODUCT ID COST ID
1 9000 21
2 600 22
3 30 23
ID in table1 is primary index and PRODUCT ID in table2 is the primary index. The common link between these two tables is ID. I used the following query to read the values.
String query = "SELECT * FROM Table1 c1 INNER JOIN Table2 c2 ON c1.ID = c2.ID";
But my problem is when I am adding new row, I use the following queries for it.
String query1 = "INSERT INTO Table1(CUSTOMER) VALUES ('" + alex + "') ";
String query2 = "INSERT INTO Table2(COST) VALUES ('" + 500 + "') ";
Since ID is not the primary index for Table2, I get a NULL value in ID. When I try to read again, since ID are not matched the I cannot reload the saved data.
Edit
This is what I have tried based on the explanation given here,
String foreignKey = "ALTER TABLE Table2 ADD FOREIGN KEY (ID) REFERENCES Table1(ID)";
Still the column ID is null in table2. Do I need combine the queries in some sort to acheive the result ? Because I just execute queries one by one as follows.
Statement stmt = connect.createStatement();
stmt.executeUpdate(query1);
stmt.executeUpdate(query2);
stmt.executeUpdate(foreignKey);
General idea here - you need to get autogenerated id from first "insert" to Table1 and set "ID" at Table2 explicitly with this id in the second "insert". You can see how to do that here for example.
Foreign key in your second table - is just a constraint, that helps to prevent data's inconsistency. Its main purpose - is to give some message to you when you're trying to put some data with foreign key that doesn't exist in primary table. Also it can help (if you set this while creating foreign key) to remove from Table2 rows linked on foreign key with Table1 when you delete row at Table1.
And you shouldn't call stmt.executeUpdate(foreignKey); each time you insert data to Table1, Table2. It should be done once when you describe the structure of your database.
Related
I have a table accounts in Postgres which had id and name as fields. id is the primary key.
I want to fetch the last primary key inserted into the table using this query :-
select id from accounts order by id desc limit 1 ;
Using a preparedStatement I run this query and get the value for my next primary key by incrementing it by 1.
String query="SELECT "+columnName+" FROM "+TableName+" ORDER BY "+columnName+" DESC limit 1";
PreparedStatement stmt=conn.prepareStatement(query);
ResultSet rs= stmt.executeQuery();
int counter= rs.getInt(1);
My question is if there are 0 rows, what will be the counter value?
If the value is null which i don't think can be stored in int, how do I assign it a starting primary int key value say 10 ?
You shouldn't be doing that, so here's what I believe is the best answer.
Instead, define your id as auto-incrementing which postgres manages:
create table account (
id serial not null primary key,
...
)
Then execute an insert:
insert into account (col1, col2, ...) values (..., ...) -- omit id
And the new account will get the next number, which you can get from the result returned from the insert, or in postgres you can use a regular query to get it
insert into account (col1, col2, ...) values (..., ...) -- omit id
returning id
Note the change in name from accounts to account - naming tables are a singular noun is best practice and makes sense: accounts.surname is nonsense, but account.surname is how we speak and think.
i have 2 tables . column of one table is part of tablename to others , i want to make join in between these tables something like below.
select ar.id,ar.type from Art ar ,CONCAT('MOK', ar.type) mo where mo.id= ar.id
There is same id present in both table but mo.id does not exist is the exception i m getting.thnx for your time. name of second table is MOKdance where dance =ar.type
Using an Oracle DB, I need to select all the IDs from a table where a condition exists, then delete the rows from multiple tables where that ID exists. The pseudocode would be something like:
SELECT ID FROM TABLE1 WHERE AGE > ?
DELETE FROM TABLE1 WHERE ID = <all IDs received from SELECT>
DELETE FROM TABLE2 WHERE ID = <all IDs received from SELECT>
DELETE FROM TABLE3 WHERE ID = <all IDs received from SELECT>
What is the best and most efficient way to do this?
I was thinking something like the following, but wanted to know if there was a better way.
PreparedStatement selectStmt = conn.prepareStatment("SELECT ID FROM TABLE1 WHERE AGE > ?");
selectStmt.setInt(1, age);
ResultSet rs = selectStmt.executeQuery():
PreparedStatement delStmt1 = conn.prepareStatment("DELETE FROM TABLE1 WHERE ID = ?");
PreparedStatement delStmt2 = conn.prepareStatment("DELETE FROM TABLE2 WHERE ID = ?");
PreparedStatement delStmt3 = conn.prepareStatment("DELETE FROM TABLE3 WHERE ID = ?");
while(rs.next())
{
String id = rs.getString("ID");
delStmt1.setString(1, id);
delStmt1.addBatch();
delStmt2.setString(1, id);
delStmt2.addBatch();
delStmt3.setString(1, id);
delStmt3.addBatch();
}
delStmt1.executeBatch();
delStmt2.executeBatch();
delStmt3.executeBatch();
Is there a better/more efficient way?
You could do it with one DELETE statement if two of your 3 tables (for example "table2" and "table3") are child tables of the parent table (for example "table1") that have a "ON DELETE CASCADE" option.
This means that the two child tables have a column (example column "id" of "table2" and "table3") that has a foreign key constraint with "ON DELETE CASCADE" option that references the primary key column of the parent table (example column "id" of "table1"). This way only deleting from the parent table would automatically delete associated rows in the child tables.
Check out this in more detail : http://www.techonthenet.com/oracle/foreign_keys/foreign_delete.php
If you delete only few records of a large tables ensure that an index on the
column ID is defined.
To delete the records from the table TABLE2 and 3 the best strategy is to use the CASCADE DELETE as proposed by
#ivanzg - if this is not possible, see below.
To delete from TABLE1 a far superior option that a batch delete on a row basis, use signle delete using the age based predicate:
PreparedStatement stmt = con.prepareStatement("DELETE FROM TABLE1 WHERE age > ?")
stmt.setInt(1,60)
Integer rowCount = stmt.executeUpdate()
If you can't cascade delete, use for the table2 and 3 the same concept as above but with the following statment:
DELETE FROM TABLE2/*or 3*/ WHERE ID in (SELECT ID FROM TABLE1 WHERE age > ?)
General best practice - minimum logic in client, whole logic in the database server. The database should be able to do reasonable execution plan
- see the index note above.
DELETE statement operates a table per statement. However the main implementations support triggers or other mechanisms that perform subordinate modifications. For example Oracle's CREATE TRIGGER.
However developers might end up figuring out what is the database doing behind their backs. (When/Why to use Cascading in SQL Server?)
Alternatively, if you need to use an intermediate result in your delete statements. You might use a temporal table in your batch (as proposed here).
As a side note, I see not transaction control (setAutoCommit(false) ... commit() in your example code. I guess that might be for the sake of simplicity.
Also you are executing 3 different delete batches (one for each table) instead of one. That might negate the benefit of using PreparedStatement.
We have multiple tables and all are related with first table's primary key (example: id). Id is configured as a sequence and while inserting data into to first table we are using sequence.nextval in the insert query.
Now while inserting data to other tables, how to get current sequence value or current Id.
We have tried below options:
sequence.currval, directly in the insert statement
2.select sequence.currval from dual
Above two options throwing error while using getJdbcTemplate().update().
Could anyone please suggest how to get current sequence value to pass to other tables after inserting data into first table??
If you want to insert the same id (which comes from a sequence) to different tables, simple get it form the first insert and use it in the other inserts.
PrepearedStatement stmt1 = conn.prepareStatement("INSERT INTO TABLE1 (id) VALUES(yoursequence.nextval)", Statemet.RETURN_GENERATED_KEYS);
stmt1.executeUpdate();
ResultSet rs = stmt1.getGeneratedKeys();
rs.next();
long id = rs.getLong(1);
PrepearedStatement stmt2 = conn.prepareStatement("INSERT INTO TABLE2 (id) VALUES(?)");
stmt2.setLong(1,id);
stmt2.executeUpdate();
I'm new in sql. I have doubt. Let's say that I have two tables. One is called user and the other order.
User
User_Id - name - email
Order
Order_id - product - User_id
What query should I use to insert a new order in the order table with the User_id field related to the User_id from the user table(an existing user)
Eg:
Order_id - product - User_id
1a - plate - 1
2a - car - 3
3a - bike - 1
If you have name or email of the user, you can try this. If USER has a composite primary key on user_id and name columns, it will work without any issues. Better to keep foreign key relationship on user_id column of ORDER also.
Example has NAME column, you can try with email column also.
INSERT INTO ORDER (ORDER_ID, PRODUCT, USER_ID)
VALUES (1a, 'plate', (SELECT USER_ID FROM USER WHERE NAME = 'Existing user'));
EDIT:
I have worked on Oracle sql only. After your comment, found this link.
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
If you have defined AUTO_INCREMENT on order_id column, you don't need to pass value.
INSERT INTO ORDER (PRODUCT, USER_ID)
VALUES ('plate', (SELECT USER_ID FROM USER WHERE NAME = 'Existing user'));
you use the standard sql insert.
insert into Order (Order_id, product, User_id) values ("3a", "bike", 1)
If your tables are set up property, there will be a foreign key restriction on the User_id field, so if you try to insert an order but don't reference a valid person, mysql will throw an error.
INSERT order (Order_id, product, User_id) VALUES (1a,plate,1)
The foreign key has nothing to do with the sql used in the insert it should have been set up when the table was created or via an ALTER TABLE query after it was created.
Relationships between tables are defined when you create the table, using the FOREIGN KEY.
CREATE TABLE Users(
UserId int primary key
);
CREATE TABLE Orders(
OrderId int primary key,
UserId int FOREIGN KEY REFERENCES Users(UserId)
);
Then you do a simple insert like:
INSERT INTO ORDER(OrderId, UserId) VALUES(1, 5);
Take a look at the documentation for foreign key constraints here: http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html.