Inserting unique values in PostgreSQL - sql

I am trying to insert the distinct values in my database:
My query is like that:
query2 = "INSERT INTO users (id, name, screenName, createdAt, defaultProfile, defaultProfileImage,\
description) SELECT DISTINCT %s, %s, %s, %s, %s, %s, %s;"
cur.execute(query2, (user_id, user_name, user_screenname, user_createdat, \
default_profile, default_profile_image, description))
However, I still get the error: psycopg2.IntegrityError: duplicate key value violates unique constraint "users_key".
I guess that the query is inserting all data and then selects the distinct values?
Another way I guess would be to store all data in a temporary database and then retrieve them for there.
But is there an easier way?
Thank you!

You appear to be trying to do an insert ... if not exists type operation. If you're on PostgreSQL 9.5 you should use INSERT ... ON CONFLICT NO ACTION. See How to UPSERT (MERGE, INSERT ... ON DUPLICATE UPDATE) in PostgreSQL? for relevant details.
SELECT DISTINCT, used the way you are using it, will not help you with this. It operates only on the rows input to the SELECT statement. It doesn't know anything about where the output rows go, in your case to a table.
You need to join against the table, or use WHERE NOT EXISTS (SELECT 1 FROM mytable WHERE ...) to make the INSERT INTO ... SELECT ...'s SELECT part return zero rows if the row already exists in the target table.
Note, though, that that's still subject to race conditions. If you have multiple concurrent clients you also need to LOCK the table.

For anyone who is looking for a way to insert unique values from one table into a table where there is no unique key (in other words, only insert rows wherein the full set of columns does not match a set of columns for an existing record in the target table)
e.g.
Table 1
column1 column2
------- -------
1. dog collar
Table 2
column1 column2
------- -------
1. dog collar
2. dog leash
Intended effect is to insert column 2 from Table 2, but not column 1 since it matches a row in Table 1.
This worked for me, albeit not very performant:
INSERT INTO table1 (
column1,
column2
)
SELECT
column1,
column2
FROM table2
WHERE (
column1,
column2
)
NOT IN
(SELECT
column1,
column2
FROM table1)

Related

Import data from SQL Server table into another table

I can't get this SQL statement right. I want to select band emails into another table but I don't understand what I'm doing wrong:
INSERT INTO submitted (mail)
SELECT
submitted.bandid,
band.mail,
band.id
FROM
band
WHERE
submitted.bandid = band.id
Can anybody help me?
Try this, you had specified 1 column to INSERT INTO but your SELECT query contained 3 columns, also the tables in your weren't joined:
INSERT INTO submitted (mail)
SELECT
band.mail
FROM band
INNER JOIN submitted ON submitted.bandid = band.id
You haven't mentioned the error message you're getting, but I suspect the problem is that you only have one column specified in the INSERT part of the statement, but the SELECT part returns many columns.
This w3schools page has a good example of how this query should be structured:
Copy only some columns from one table into another table:
INSERT INTO table2 (column1, column2, column3, ...)
SELECT column1, column2, column3, ...
FROM table1
WHERE condition;
I suspect you want update, not insert:
UPDATE s
SET mail = b.mail
FROM submitted s JOIN
band b
ON s.bandid = b.id;
insert inserts new rows into the table. update updates columns in existing rows.

Selectively insert rows based on if the row already exists or not

I currently have a table that has several thousand entries. I've found a way to insert of a new row of data for all entries in the system (see example below), but unfortunately, I just found out that some of the entries have the value already in there. I'm trying to figure out how to selectively run the INSERT INTO function based on if the row already exists or not.
Column 1 Column 2 Column 3
10 Address True
10 City False
10 State True
20 Address True
20 City True
20 State True
20 NEW NEW*
Column 1 Column 2 Column 3
10 Address True
10 City False
10 State True
10 NEW NEW
20 Address True
20 City True
20 State True
20 NEW NEW
The code I've used for the insert is:
insert into table-name(Column1, Column2, Column3)
select
Column1, 'NEW', 'NEW*'
from
table-name
group by
Column1
I'm assuming I need to use an IF/ELSE statement, but I'm running into issues on the IF statement. Currently, I'm using the following code:
IF Column 2 like 'New' leave NULL
ELSE
insert into table-name(Column1, Column2, Column3)
select
Column1, 'NEW', 'NEW*'
from table-name
group by Column1
I know the IF statement is wrong, but trying to figure out what to do to leave the existing row values the same if they are already populated.
Using SQL Server, you can do a NOT EXISTS
insert into table-name(Column1, Column2, Column3)
select
Column1, 'NEW', 'NEW*'
from
table-name
WHERE NOT EXISTS (SELECT 1 FROM table-name xref WHERE xref.Column1 = table-name.Column1 AND xref.Column2 = 'NEW')
group by
Column1
You can use the INSERT IGNORE INTO
or INSERT … ON DUPLICATE KEY UPDATE syntax
see http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html
and
dev.mysql.com
I think what you want is an "INSERT INTO" with an "ON DUPLICATE KEY".
See:
http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
For SQL Server use a CTE to define your dataset to be inserted:
WITH NonDupes (<your fieldlist>)
AS
(SELECT <your fieldlist> FROM <your tables> WHERE <tablea>.<column> NOT IN (SELECT <column> FROM <tableb>))
INSERT INTO
<tableb>
VALUES(SELECT * FROM NonDupes)
You can use a Merge statement to insert only rows that don't exist. As an added bonus you can update existing rows in the same statement if you need to do that.
http://msdn.microsoft.com/en-us/library/bb510625.aspx

SQL SELECT INSERT INTO Generate Unique Id

I'm attempting to select a table of data and insert this data into another file with similar column names (it's essentially duplicate data). Current syntax as follows:
INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT similiarId, similiarId2, similiarCol1, similiarCol2
FROM TABLE2
The problem I have is generating unique key fields (declared as integers) for the newly inserted records. I can't use table2's key's as table1 has existing data and will error on duplicate key values.
I cannot change the table schema and these are custom id columns not generated automatically by the DB.
Does table1 have an auto-increment on its id field? If so, can you lose similiarId from the insert and let the auto-increment take care of unique keys?
INSERT INTO TABLE1 (id2, col1, col2) SELECT similiarId2, similiarCol1, similiarCol2
FROM TABLE2
As per you requirement you need to do you query like this:
INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT (ROW_NUMBER( ) OVER ( ORDER BY ID ASC ))
+ (SELECT MAX(id) FROM TABLE1) AS similiarId
, similiarId2, similiarCol1, similiarCol2
FROM TABLE2
What have I done here:
Added ROW_NUMBER() which will start from 1 so also added MAX() function for ID of destination table.
For better explanation See this SQLFiddle.
Im not sure if I understad you correctly:
You want to copy all data from TABLE2 but be sure that TABLE2.similiarId is not alredy in TABLE1.id, maybe this is solution for your problem:
DECLARE #idmax INT
SELECT #idmax = MAX(id) FROM TABLE1
INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT similiarId + #idmax, similiarId2, similiarCol1, similiarCol2
FROM TABLE2
Now insert will not fail because of primary key violation because every inserted id will be greater then id witch was alredy there.
If the id field is defined as auto-id and you leave it out of the insert statement, then sql will generate unique id's from the available pool.
In SQL Server we have the function ROW_NUMBER, and if I have understood you correctly the following code will do what you need:
INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT (ROW_NUMBER( ) OVER ( ORDER BY similiarId2 ASC )) + 6 AS similiarId,
similiarId2, similiarCol1, similiarCol2
FROM TABLE2
ROW_NUMBER will bring the number of each row, and you can add a "magic value" to it to make those values different from the current max ID of TABLE1. Let's say your current max ID is 6, then adding 6 to each result of ROW_NUMBER will give you 7, 8, 9, and so on. This way you won't have the same values for the TABLE1's primary key.
I have asked Google and it said to me that Sybase has the function ROW_NUMBER too (http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.sqlanywhere.12.0.1/dbusage/ug-olap-s-51258147.html), so I think you can try it.
If you want to make an identical table why not simply use (quick and dirty) Select INTO method ?
SELECT * INTO TABLE2
FROM TABLE1
Hope This helps.
Make the table1 ID IDENTITY if it is not a custom id.
or
Create new primary key in table1 and make it IDENTITY, and you can keep the previous IDs in the same format (but not primary key).
Your best bet may be to add an additional column on Table2 for Table1.Id. This way you keep both sets of Keys.
(If you are busy with a data merge, retaining Table1.Id may be important for any foreign keys which may still reference Table1.Id - you will then need to 'fix up' foreign keys in tables referencing Table1.Id, which now need to reference the applicable key in table 2).
If you need your 2nd table keep similar values as in 1st table , then donot apply auto increment on 2nd table.
If you have large range, and want easy fast make and don't care about ID:
Example wit CONCAT
INSERT INTO session(SELECT CONCAT("3000", id) as id, cookieid FROM `session2`)
but you can using also REPLACE

How to insert row for each unique value found in column

How could I, in SQL Server 2008, write a SQL statement that would insert one row for each distinct value it finds in one column in the same table?
Edit:
The table I want to add rows to the same table I'm checking.
I have normalized table with a column [Name], and [Hobby], so how do I insert one new hobby for each name?
Input greatly appreciated =]
try
INSERT INTO TargetTable (SomeColumn)
SELECT DISTINCT TheSourceColumn From SomeSourceTable;
IF that is not what you are looking for please provide more details like what the data model looks like etc.
UPDATE - after edit from OP:
I am not sure that you data model is good but you can do this:
INSERT INTO TheTable (NAME, HOBBY)
SELECT DISTINCT X.NAME, #SomeHOBBY FROM TheTable X;
You could use something like
Insert into table1
Select distinct col1 from tabl2
The above should work as long as table1 has just one column of the same data type as col1 of tabl2

Can I select a set of rows from a table and directly insert that into a table or the same table in SQL?

Hi all I was just curious if I could do something like -
insert into Employee ( Select * from Employee where EmployeeId=1)
I just felt the need to do this a lot of times...so just was curious if there was any way to achieve it..
You can do something like that, but you cannot Select * if you want to change a column value:
Insert into employee ( employeeId, someColumn, someOtherColumn )
Select 2, someColumn, someOtherColumn
From employee
Where employeeId=1
This would insert 2 as your new employeeId.
yes list out the column and do it like that
insert into Employee (EmployeeId, LastName, FirstName......)
Select 600 as EmployeeId, LastName, FirstName......
from Employee where EmployeeId=1
However if EmployeeId is an identity column then you also need to do
set identity_insert employee on
first and then
set identity_insert employee off
after you are done
You could use the INSERT INTO ... SELECT ... syntax if the destination table already exists, and you just want to append rows to it. It's easy to check if you are selecting your data by executing just the SELECT part.
Insert into existingTable ( Column1, Column2, Column3, ... )
Select 1, Column2, Column3
From tableName
Where ....
You are not restricted to a simple select, the SELECT statement can be as complex as necessary. Also you do not need to provide names for the selected columns, as they will be provided by the destination table.
However, if you have autoincrement columns on the dest table, you can either omit them from the INSERT's column list or use the 'set identity_insert' configuration.
If you want to create a new table from existing data, then you should use the SELECT ... INTO ... syntax
Select 1 as Column1, Column2, Column3
Into newTable
From tableName
Where ....
Again, the select can be arbitrarily complex, but, because the column names are taken from the select statement, all columns must have explicit names. This syntax will give an error if the 'newTable' table already exists. This form is very convenient if you want to make a quick copy of a table to try something.