I'm working on my first db and executing statements through java. I have 2 columns in the db named
Playername
PlayerType
I need to update the row if my query corresponds to these 2 columns.
So there can be multiple player names and multiple player types but never more than 1 exact player type and exact player name.
If the row doesn't exist create a new one. What's the best way to go about this?
You first have to set a multiple field primary key
CREATE TABLE Players
(
PlayerName varchar(16) NOT NULL, //Not null not required as it is part of pk but more readable
PlayerType varchar(16) NOT NULL,
//Other fields
CONSTRAINT pk_PlayersID PRIMARY KEY (PlayerName ,PlayerType )
)
And then you use
INSERT INTO Players(PlayerName , PlayerType ,....) VALUES(PN, PT, ....) ON DUPLICATE KEY UPDATE
PlayerName VALUES(PlayerName ), PlayerType =VALUES(PlayerType ),...
Related
I am creating a program which is a Car Management app in Java using Swing in Netbeans, and as the database I am using Mysql, which will do all the CRUD operation. I have created a database with 3 different tables.
DATABASE SCHEMA
CREATE TABLE car_make(
make_id INT NOT NULL AUTO_INCREMENT
make VARCHAR(50)
PRIMARY KEY(make_id)
)
CREATE TABLE car_model(
model_id INT NOT NULL AUTO_INCREMENT
model VARCHAR(50)
fk_make_id INT
PRIMARY KEY(model_id)
FOREIGN KEY(fk_make_id) REFERENCES car_make(make_id)
)
CREATE TABLE car_attributes(
car_attr_id INT NOT NULL AUTO_INCREMENT
fk_make_id INT
fk_model_id INT
year INT
body_type VARCHAR(50)
mileage INT
price DECIMAL(6,2)
PRIMARY KEY(car_attr_id )
FOREIGN KEY(fk_make_id) REFERENCES car_make(make_id)
FOREIGN KEY(fk_model_id) REFERENCES car_model(model_id )
);
The car_make table is already populated with all the car makes which I inserted manually and their ID's were auto generated. And the car_model table is also populated with different models for each make.
I have also created the user interface in netbeans using Java Swing, where the user selects the make of the car which will automatically generate the corresponding model, the year, mileage and so on and insert all that data into the car_attribute tables. My question is, what is the query to insert the car make and model into the car_attribute table as foreign keys. For example if the user chooses as Make-BMW and Model-5 Series, I want to insert both of those IDS into the third table.
this scenario came up when you want to add new car, so the GUI show you the CAR_MAKEs
when you choose, it will show you CAR_MODELs, then you need to STORE the ID of fetched data (car_makes OR car_models) in arrayList and use it in the query when the USER submit
Just pseudo code
int carMakesSelectedIndex = comboCarMakes.getSelectedIndex();
int carModelsSelectedIndex = comboCarModels.getSelectedIndex();
PreparedStatement stmt=con.prepareStatement("insert into car_attributes values(?,?,?,?,?,?,?,?,?,?)");
stmt.setInt(1,carAttribute);
stmt.setInt(2,carMakesIdList.get( carMakesSelectedIndex ) );
stmt.setInt(3,carMakesIdList.get( carModelsSelectedIndex ) );
stmt.setString(4,carYear );
// the same with other attribute
I'm very new to SQL and I want the contracts_tb (query details below) is to display and link the foreign id keys referred from:
med_idref (referred from med_id (INTEGER), PRIMARY KEY o mediaadv_tb),
mediatitle_ref (title (TEXT), mediaadv_tb),
mediatype_red (mtype (TEXT), mediaadv_tb),
cus_idref (cus_id (INTEGER),PRIMARY KEY of customer_tb),
cus_companyref (referred from company (TEXT), in customer_tb)
All to be linked and displayed to contracts_tb. When I add/replace values from mediaadv_tb and customer_tb, I get this problem:
foreignkey mismatch
Also, do I have to make or assign a parent table?
Query:
DROP TABLE IF EXISTS customer_tb;
CREATE TABLE IF NOT EXISTS customer_tb (
cus_id INTEGER PRIMARY KEY,
company TEXT,
firstname TEXT,
middlename TEXT,
lastname TEXT,
gender TEXT,
dob TEXT,
dateregistered TEXT,
contactno TEXT,
emailaddress TEXT,
description TEXT,
refpic INTEGER,
cuspic BLOB
);
DROP TABLE IF EXISTS mediaadv_tb;
CREATE TABLE IF NOT EXISTS mediaadv_tb (
med_id INTEGER PRIMARY KEY,
mtype TEXT,
duration TEXT,
title TEXT,
dateadded TEXT,
desription TEXT,
previewimg BLOB,
filepath TEXT
);
DROP TABLE IF EXISTS contracts_tb;
CREATE TABLE IF NOT EXISTS contracts_tb (
contract_id INTEGER PRIMARY KEY,
customer_idref INTEGER REFERENCES customer_tb (cus_id),
media_idref INTEGER REFERENCES mediaadv_tb (med_id),
media_typeref TEXT REFERENCES mediaadv_tb(mtype),
media_titleref TEXT REFERENCES mediaadv_tb (title),
status TEXT,
priority TEXT,
dateadded TEXT,
dateexpiration TEXT,
amountpaid REAL,
arearofcoverage TEXT
);
Error :-
contracts_tb
mediaadv_tb
I believe that your issue is because the foreign keys defined that reference the media_typeref and the media_titleref columns are invalid as they do not have, or are part of a, UNIQUE indexes (no indexes). SQLite Foreign Key Support - 3. Required and Suggested Database Indexes
The referenced id columns, as they are INTEGER PRIMARY KEY, are implicitly UNIQUE indexes.
Furthermore the two columns (typeref and titleref) themself aren't even needed as the media_idref column would be used to identify the reference and thus would hold the respective values. Copying those values into the contracts table would be contrary to normalisation and may even create major headaches (e.g. if a value changed you'd have to find all other uses and also change them).
As such I'd suggest that the contracts_tb be created using :-
DROP TABLE IF EXISTS contracts_tb;
CREATE TABLE IF NOT EXISTS contracts_tb (
contract_id INTEGER PRIMARY KEY,
customer_idref INTEGER REFERENCES customer_tb (cus_id),
media_idref INTEGER REFERENCES mediaadv_tb (med_id),
status TEXT,
priority TEXT,
dateadded TEXT,
dateexpiration TEXT,
amountpaid REAL,
arearofcoverage TEXT
);
Re comment :-
What i'm making is a Java NetBeans SQLite database program, where by
using the Contracts frame, whevenr one makes a new contract, there
will be a combobox that restricts the user to only put the existing
ids or names that is referred in the contracts_tb then provides the
choices. Is it possible sir?
Yes.
More specifically:-
Assume that you have customers Fred, Bert and Harry (id's 1,2 and 3 respectively). And that you have mediaadv's M1, M2 and M3 (id's 10,11 and 12 (not 1,2 and 3 to help distinguish between mediaadv and customers)).
Additionally I'll assume the suggested contracts_tb table as opposed to the original in the question (i.e. 2 columns dropped as suggested)
The when inserting a new contract, you present a list (combobox) of the customers e.g.
Fred
Bert
Harry
(this list could be generated from a query such as:-
SELECT cus_id,firstname FROM customer_tb; i.e. all existing customers)
If you wanted Fred James Bloggs then you could use :-
SELECT cus_id,firstname||' '||middlename||'lastname' AS fullname FROM customer_tb;.
Likewise a list of the existing mediaadv could be generated from a query such as:-
SELECT med_id, description FROM mediaadv_tb; e.g.
so the combobox would have:-
M1
M2
M3
Now if the contract were for Bert (id 2) and M1 (id 10) then you build SQL something like :-
INSERT INTO contracts_tb VALUES(null,2,10,'the_status','the_priority','yyyy-mm-dd','yyyy-mm-dd',500,'the_coverage');
1st value is null i.e. no value, so as contract_id is an alias of the rowid it will be generated.
2 is the id of the customer (hence why cus_id was in the query as you need the id as it's the value you are going to store)
10 is the id of the mediaadv (again hence why med_id was in the query as you need the id as it's the value you are going to store).
the other values are what they should be.
Note the above use of INSERT requires that all columns be given. You can skip columns by specifying a list of the columns e.g. INSERT INTO contracts_tb (customer_idref,media_idref) VALUES(2,10);
As a customer with an cus_id of 2 (Bert) exists then the constraint that customer_idref is an existing id in the customer_tb is good/met and there is no conflict.
Likewise as there is a row in mediaadv_tb that has an med_id of 10 this constraint is good/met and there is no conflict.
However say the SQL were :-
INSERT INTO contracts_tb VALUES(null,2,100,'the_status','the_priority','yyyy-mm-dd','yyyy-mm-dd',500,'the_coverage');
Then as there is no med_id of 100 the constraint saying that media_idref must reference a value of 100 (in this instance) in the mediaadv_tb, column med_id, then the constraint will not be met and the insert will fail.
So again Yes, I believe that what you want is feasible.
Note a foreign key is only a constraint it doesn't bind/associate columns or join tables.
Using MySQL, I have the following SQL Table definition:
CREATE TABLE books (
author INT,
book INT,
name VARCHAR(128),
PRIMARY KEY(author, book)
);
What I want is that I have an Id for author that I set manually and an Id for book that is incremented for each author id. Therefore I created a trigger like so:
CREATE TRIGGER trBooks
BEFORE INSERT ON books
FOR EACH ROW SET NEW.book = (
SELECT COALESCE(MAX(book), -1) + 1 FROM books
WHERE author = NEW.author
);
This works fine for me. But now I need to know the book id that was set for my inserted entry that I inserted in Java. Something like the Insert with Output as in MSSQL or a Statement.executeQuery("INSERT ..."). The solution has to be thread safe, so a separate INSERT and SELECT is no good solution, since there might have been another INSERT in the meantime.
Thanks for your help!
Your data model just doesn't make sense. You have two entities, "books" and "authors". These should each be represented as a table. Because a book can have multiple authors and an author can write multiple books, you want a junction table.
This looks like this:
CREATE TABLE Books (
BookId INT auto_increment primary key,
Title VARCHAR(255)
);
CREATE TABLE Authors (
AuthorId INT auto_increment primary key,
Name VARCHAR(255)
);
CREATE TABLE BookAuthors (
BookAuthorId INT auto_increment primary key,
AuthorId INT,
BookId INT,
CONSTRAINT fk_BookAuthor_BookId FOREIGN KEY (BookId) REFERENCES Books(BookId),
CONSTRAINT fk_BookAuthor_AuthorId FOREIGN KEY (BookId) REFERENCES Authors(AuthorId),
UNIQUE (AuthorId, BookId)
);
As for your question about inserts. You don't need a trigger to set auto-incremented ids. You can use LAST_INSERT_ID() to fetch the most recent inserted value.
i have 2 table
1 persons(email,name)
2 location(email)
now when i add a person to persons table i want the db auto creat a row in location whit the person email (that i just add to persons).
i try to do it white PRIMARY KEY, and FOREIGN KEY but no succses.
thank you all.
this what i try :
CREATE TABLE Persons
(
Email char(50) PRIMARY KEY,
First_Name char(50))
CREATE TABLE location
(
email char(50),
FOREIGN KEY (email) REFERENCES Persons(email)
)
but when i add to persons person its not added to location too.
You would need a trigger to do this not a foreign key.
The FK just enforces that a row cannot be inserted in location without a corresponding record in Persons
But email is a very wide choice for a primary key as well as unstable (see is email address a bad primary key) and the whole design seems odd.
What is the location table for? Does this have a 1:many relationship with Persons? Where are the other columns? What is the PK of location?
i have two tables where in the first one i have 14 millions and in the second one i have 1.5 million of data.
So i wonder how could i transfer this data to another table to be normalized ?
And how do i convert some type to another, for example: i have a field called 'year' but its type is varchar, but i want it an integer instead, how do i do that ?
I thought about do this using JDBC in a loop while from java, but i think this is not effeciently.
// 1.5 million of data
CREATE TABLE dbo.directorsmovies
(
movieid INT NULL,
directorid INT NULL,
dname VARCHAR (500) NULL,
addition VARCHAR (1000) NULL
)
//14 million of data
CREATE TABLE dbo.movies
(
movieid VARCHAR (20) NULL,
title VARCHAR (400) NULL,
mvyear VARCHAR (100) NULL,
actorid VARCHAR (20) NULL,
actorname VARCHAR (250) NULL,
sex CHAR (1) NULL,
as_character VARCHAR (1500) NULL,
languages VARCHAR (1500) NULL,
genres VARCHAR (100) NULL
)
And this is my new tables:
DROP TABLE actor
CREATE TABLE actor (
id INT PRIMARY KEY IDENTITY,
name VARCHAR(200) NOT NULL,
sex VARCHAR(1) NOT NULL
)
DROP TABLE actor_character
CREATE TABLE actor_character(
id INT PRIMARY KEY IDENTITY,
character VARCHAR(100)
)
DROP TABLE director
CREATE TABLE director(
id INT PRIMARY KEY IDENTITY,
name VARCHAR(200) NOT NULL,
addition VARCHAR(150)
)
DROP TABLE movie
CREATE TABLE movie(
id INT PRIMARY KEY IDENTITY,
title VARCHAR(200) NOT NULL,
year INT
)
DROP TABLE language
CREATE TABLE language(
id INT PRIMARY KEY IDENTITY,
language VARCHAR (100) NOT NULL
)
DROP TABLE genre
CREATE TABLE genre(
id INT PRIMARY KEY IDENTITY,
genre VARCHAR(100) NOT NULL
)
DROP TABLE director_movie
CREATE TABLE director_movie(
idDirector INT,
idMovie INT,
CONSTRAINT fk_director_movie_1 FOREIGN KEY (idDirector) REFERENCES director(id),
CONSTRAINT fk_director_movie_2 FOREIGN KEY (idMovie) REFERENCES movie(id),
CONSTRAINT pk_director_movie PRIMARY KEY(idDirector,idMovie)
)
DROP TABLE genre_movie
CREATE TABLE genre_movie(
idGenre INT,
idMovie INT,
CONSTRAINT fk_genre_movie_1 FOREIGN KEY (idMovie) REFERENCES movie(id),
CONSTRAINT fk_genre_movie_2 FOREIGN KEY (idGenre) REFERENCES genre(id),
CONSTRAINT pk_genre_movie PRIMARY KEY (idMovie, idGenre)
)
DROP TABLE language_movie
CREATE TABLE language_movie(
idLanguage INT,
idMovie INT,
CONSTRAINT fk_language_movie_1 FOREIGN KEY (idLanguage) REFERENCES language(id),
CONSTRAINT fk_language_movie_2 FOREIGN KEY (idMovie) REFERENCES movie(id),
CONSTRAINT pk_language_movie PRIMARY KEY (idLanguage, idMovie)
)
DROP TABLE movie_actor
CREATE TABLE movie_actor(
idMovie INT,
idActor INT,
CONSTRAINT fk_movie_actor_1 FOREIGN KEY (idMovie) REFERENCES movie(id),
CONSTRAINT fk_movie_actor_2 FOREIGN KEY (idActor) REFERENCES actor(id),
CONSTRAINT pk_movie_actor PRIMARY KEY (idMovie,idActor)
)
UPDATE:
I'm using SQL Server 2008.
Sorry guys i forgot to mention that are different databases :
The not normalized is call disciplinedb and the my normalized call imdb.
Best regards,
Valter Henrique.
If both tables are in the same database, then the most efficient transfer is to do it all within the database, preferably by sending a SQL statement to be executed there.
Any movement of data from the d/b server to somewhere else and then back to the d/b server is to be avoided unless there is a reason it can only be transformed off-server. If the destination is different server, then this is much less of an issue.
Though my tables were dwarfs compared to yours, I got over this kind of problem once with stored procedures. For MySQL, below is a simplified (and untested) essence of my script, but something similar should work with all major SQL bases.
First you should just add a new integer year column (int_year in example) and then iterate over all rows using the procedure below:
DROP PROCEDURE IF EXISTS move_data;
CREATE PROCEDURE move_data()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE orig_id INT DEFAULT 0;
DECLARE orig_year VARCHAR DEFAULT "";
DECLARE cur1 CURSOR FOR SELECT id, year FROM table1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
PREPARE stmt FROM "UPDATE table1 SET int_year = ? WHERE id = ?";
read_loop: LOOP
FETCH cur1 INTO orig_id, orig_year;
IF done THEN
LEAVE read_loop;
END IF;
SET #year= orig_year;
SET #id = orig_id;
EXECUTE stmt USING #orig_year, #id;
END LOOP;
CLOSE cur1;
END;
And to start the procedure, just CALL move_data().
The above SQL has two major ideas to speed it up:
Use CURSORS to iterate over a large table
Use PREPARED statement to quickly execute pre-known commands
PS. for my case this speeded things up from ages to seconds, though in your case it can still take a considerable amount of time. So it would be probably best to execute from command line, not some web interface (e.g. PhpMyAdmin).
I just recently did this for ~150 Gb of data. I used a pair of merge statements for each table. The first merge statement said "if it's not in the destination table, copy it there" and the second said "if it's in the destination table, delete it from the source". I put both in a while loop and only did 10000 rows in each operation at a time. Keeping it on the server (and not transferring it through a client) is going to be a huge boon for performance. Give it a shot!