Can I write an insert query using data from two joined tables? - sql

I have a SELECT query like this:
SELECT id_default_value, id_type FROM ntg_attribute, ntg_module_attribute
WHERE ntg_attribute.id_module_attribute = ntg_module_attribute.id;
This returns 2 columns, id_default_value and id_type. I'd like to then use this data as the basis of an INSERT query into another table, ntg_default_value, using id_default_value as the key, and id_type as the inserted value.
The following is nearly there, but not quite:
INSERT INTO ntg_default_value (id, id_type)
SELECT id_default_value, id_type FROM ntg_attribute, ntg_module_attribute
WHERE ntg_attribute.id_module_attribute = ntg_module_attribute.id;
This gives me:
ERROR: duplicate key value violates unique constraint "pk_ntg_default_value"
Is what I'm trying to do actually possible? If so, how do I construct the query?
(PostgreSQL 8.4.6)

The name of the constraint 'pk_ntg_default_value' probably means you are violating the primary key constraint of the table ntg_default_value.
Depending on your requirements you can either take away the primary key constraint. Or you can expand it to include both id & id_type if it doesn't already and add a GROUP BY to your query, if necessary, to prevent duplicate id_devault_value & id_type pairs. Your query becomes then :
INSERT INTO ntg_default_value (id, id_type)
SELECT id_default_value, id_type
FROM ntg_attribute, ntg_module_attribute
WHERE ntg_attribute.id_module_attribute =
ntg_module_attribute.id
GROUP BY id_default_value, id_type

Related

query without using subquery or explicit join

I need to re-write this without using subquery and explicit join..help please been looking around for a while
SELECT snum, pnum, shipdate
FROM supply as b
WHERE EXISTS (SELECT pname, pnum FROM parts as a WHERE b.pnum = a.pnum);
I believe you've been given a trick question. The answer is this.
SELECT snum, pnum, shipdate
FROM supply
The reason is that the condition you're checking for should be impossible in a well designed database.
Let's have a look at what the original query is doing.
SELECT snum, pnum, shipdate
FROM supply as b
WHERE EXISTS (
SELECT pname, pnum FROM parts as a WHERE b.pnum = a.pnum
);
It's getting every row in supply where there's a corresponding part in parts. How do you do this in a query without a join? You shouldn't have to do it in the first place. Instead you should rely on referential integrity.
Referential integrity is a property of good table design that says all references are valid. There should be no need to check that each part in supply exists in parts because such a condition should be impossible. You do this with a well designed schema with appropriate use of foreign key and not null constraints.
(My examples are done in Postgres. The syntax for your database may vary.)
create table parts(
pnum integer primary key,
pname text not null
);
create table supply(
snum integer primary key,
pnum integer references parts(pnum) not null,
shipdate date not null
);
By declaring supply.pnum as references parts(pnum) we have told the database this is a foreign key and there must be a corresponding row in parts. Adding not null guarantees each row in supply must supply a valid part. The database enforces these constraints automatically.
(Note that MySQL takes a little more convincing to enforce a foreign key constraint. Because MySQL is so non-standard one can pick up bad habits learning on it. Use Postgres or even SQLite instead.)
You can also add the constraints to an existing table using alter table.
test=> alter table supply alter pnum set not null;
ALTER TABLE
test=> alter table supply add constraint pnum_fk foreign key (pnum) references parts(pnum);
ALTER TABLE
For example, let's say we have these parts.
test=> select * from parts;
pnum | pname
------+---------
1 | flange
2 | thingy
3 | whatsit
We can insert a row into supply for one of those parts.
test=> insert into supply (pnum, shipdate) values (3, '2018-02-03');
INSERT 0 1
But if we try to insert a part that doesn't exist, we get an error.
test=> insert into supply (pnum, shipdate) values (99, '2018-02-03');
ERROR: insert or update on table "supply" violates foreign key constraint "supply_pnum_fkey"
DETAIL: Key (pnum)=(99) is not present in table "parts".
Or one with a null part number...
test=> insert into supply (pnum, shipdate) values (null, '2018-02-03');
ERROR: null value in column "pnum" violates not-null constraint
DETAIL: Failing row contains (1, null, 2018-02-03).
The condition you're testing for is now impossible. There's no need for it. So the answer is:
SELECT snum, pnum, shipdate
FROM supply
One way is INTERSECT(column list is limited to common ones):
SELECT pnum
FROM supply
INTERSECT
SELECT pnum
FROM parts;
Using SEMIJOIN:
SELECT b.snum, b.pnum, b.shipdate
FROM supply as b
SEMIJOIN parts as a
ON b.pnum = a.pnum;
The subquery can be replaced by an INNER JOIN, as follows :
SELECT b.snum, b.pnum, b.shipdate
FROM
supply as b
INNER JOIN parts as a ON b.pnum = a.pnum
GROUP BY b.snum, b.pnum, b.shipdate
You could also go for implicit join, but I would not recommend it as it is less readable and out of favor as of now :
SELECT b.snum, b.pnum, b.shipdate
FROM
supply as b,
parts as a
WHERE b.pnum = a.pnum
GROUP BY b.snum, b.pnum, b.shipdate

Oracle inserting into table with composite key

I have a table, TBL_1, with the following fields:
TBL_ID NUMBER (pk),
CREATE_DATE DATE (pk),
TBL_IND VARCHAR2(1)
The primary key is on TBL_ID and CREATE_DATE, I am trying to perform an insert statement but getting an error ORA-00001: unique constraint (primary key) violated.
There is a before insert trigger setting the NEW.CREATE_DATE as SYSDATE. The insert statement looks like:
INSERT INTO TBL_1 (tbl_id,tbl_ind)
SELECT tbl_id,'Y'
FROM tbl_info;
The actual query is a little more complex but I just wanted to point out it is a INSERT INTO SELECT statement. Is it possible if there is a duplicate tbl_id the trigger used the same exact date for both rows thus causing a duplicate error? How can I avoid this?
I don't think it is a good idea to have create_date as part of the primary key. I would suggest that you use a sequence value instead.
If you don't mind reducing the number of rows, you can do:
INSERT INTO TBL_1 (tbl_id,tbl_ind)
SELECT DISTINCT tbl_id, 'Y'
FROM tbl_info;
Or, if you still want all rows inserted, then restructure your data to use a sequence instead of the creation date.

SQL Server - ignoring always true condition

I need to add to the WHERE clause one condition, which is always true, but it must reference one of the columns, for example:
ID is the primary key (and therefore NOT NULL)
and I will execute a select:
SELECT *
FROM Table
WHERE ID IS NOT NULL
Will this condition be ignored or checked for every row?
SQL Server can determine at compile time that this condition will always be true and avoid the need to check at runtime.
CREATE TABLE #T
(
ID INT CONSTRAINT PK_ID PRIMARY KEY NONCLUSTERED,
X INT CONSTRAINT UQ_X UNIQUE
)
SELECT X
FROM #T
WHERE ID IS NOT NULL;
DROP TABLE #T
In the execution plan above the only index accessed is UQ_X and this doesn't even contain the ID column that would make such a runtime evaluation possible.
By contrast if ID is nullable (and replaced with a unique constraint rather than primary key as a PK wouldn't allow NULL) then the check would of course need to be made at run time and so the plan will need to retrieve the column and might look like one of the following.
Scans whole table with predicate pushed into scan
Attempt to use narrower index requires lookup to retrieve the column and evaluate the predicate
When you execute following query:
SELECT * FROM Table WHERE ID IS NOT NULL;
It will display all the rows in your table given that ID is defined as the primary key. This will be similar to SELECT * FROM Table; from the display point of view. However, the condition will not be ignored.(i.e. the where clause will be checked)
SELECT *
FROM TableName
WHERE (ID IS NOT NULL)
All the data where ID is not null will be displayed.
Id will not be null if ID is primary key in the table !
Hence you will get all the datas from the table

Copy data from a table, into the same table with a different key

I was curious if it was possible to take data from a table, and duplicate it but assign a new primary key
for example, I wish to take data that has a column "question_id" which acts as the unique key for the table, and copy all of the data from the table with that question_id to the same table but with a new question_id.
any thoughts as to if this is possible using SQL?
my database is an ingres database
thanks in advance
Sure, something like this should work:
INSERT INTO YourTable (Question_Id, OtherField,...)
SELECT SomeNewQuestionId, OtherField,...
FROM YourTable
WHERE Question_Id = SomeQuestionId
Just replace SomeQuestionId and SomeNewQuestionId with the appropriate values.
It's a simple select query.
insert into mytable
(field2, field3, etc)
select field2, field3, etc
from mytable
where whatever.
This assumes that neither fields 2 nor 3 are the primary key, and that you have an autoincrement table.
Fast forward two years.... :)
I think this is the best and simplest way to do this. Inserting a row of data from the same table with a primary key will result in error because primary keys are unique for each row: Let question_id = 100.
INSERT INTO MyTable SELECT * FROM MyTable Where question_id=100;
In PostgreSQL:
ERROR: duplicate key value violates unique constraint "MyTable_pkey"
DETAIL: Key (question_id)=(100) already exists.
It is very simple to avoid the duplicate key value:
INSERT INTO MyTable SELECT (SELECT MAX(question_id)+1),Column1,Column2,etc FROM MyTable Where question_id=100;
By using MAX(question_id)+1, you are incrementing the maximum value of MyTable's question_id primary key, then add/copy the data to a new row with a unique question_id value.

SQL - How can I apply a "semi-unique" constraint?

I have a (simplified) table consisting of three columns:
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
foreignID INT NOT NULL,
name VARCHAR NOT NULL
Basically, I would like to add a constraint (at the database level rather than at the application level) where it only possible for one unique 'name' to exist per foreignID. For example, given the data (id, foreignid, name):
1,1,Name1
2,1,Name2
3,1,Name3
4,2,Name1
5,2,Name2
I want the constraint to fail if the user tries to insert another 'Name3' under foreignId 1, but succeed if the user tries to insert 'Name3' under foreignId 2. For this reason I cannot simply make the whole column UNIQUE.
I am having difficulty coming up with a SQL expression to achieve this, can anybody help me?
Thanks
Add a unique constraint on (ForeignID, Name). The exact syntax for that depends on your DBMS. For SQL Server:
CREATE UNIQUE INDEX IndexName ON YourTable (ForeignID, Name)
(The terms "unique constraint", "unique key" and "unique index" mean roughly the same.)
create a composite (multiple - column ) key... on those two columns
Create Unique Index MyIndexName On TableName(ForeignID, Name)