Insert & Select - sql

I am trying to create a column EAC into Projectdetails.
Table 1 : [Projectdetails]
Table 2 : ['RAC']
(SELECT b.[EAC] FROM [dbo].[Projectdetails] a
INNER JOIN [dbo].['RAC'] b ON a.[ProjectKey]= b.[Project _ID])
works fine and return me 421 rows.
However the following query does not work :
Insert into [dbo].[Projectdetails]([EAC])
(SELECT b.[EAC] FROM [dbo].[Projectdetails] a
INNER JOIN [dbo].['RAC'] b ON a.[ProjectKey]= b.[Project _ID])
returns me Cannot insert the value NULL into column ProjectKey

I suspect you really want an update:
update pd
set EAC = r.EAC
from [dbo].[Projectdetails] pd join
[dbo].['RAC'] r
on pd.[ProjectKey] = r.[Project _ID]);
By the way, putting single quotes in a table name seems like a really bad idea.

I guess, ProjectKey is a primary key as it's NOT NULL. So when you are
trying to insert new row in this table without providing any specific
value for this column, so sqlserver is trying to add NULL as a default
value. But as this is NOT NULL column it's giving you error.
The best solution to make it work is make this column as
auto-increment column. Like this
Sql Server add auto increment primary key to existing table
SQL Server, How to set auto increment after creating a table without data loss?

Related

How to update column with data from another table? - SQL Server 12.0.5

I am trying to update the column "efficiency" in the table "SUS_WK" with the data from the column "custom_number_8" from the table "SC_PROD". But I only want it to update if certain requirements are met, such as the "ID" from table "SUS_WK" matches the "ID" from the table "SC_PROD".
How can I do this?
I have tried to do this:
UPDATE SUS_WK
SET efficiency = SC_PROD.custom_number_8
FROM SUS_WK t
JOIN SC_PROD p
ON t.id = p.id
When I tried the code above, I get the following error:
The multi-part identifier "SC_PROD_PLAN_PLND.custom_number_8" could not be bound.
But I expect the result of that code to update the column "efficiency" in the "SUS_WK" with the data from column "custom_number_8" in the table "SC_PROD".
You are on the right track. Just use the table alias rather than the table name:
UPDATE t
SET efficiency = p.custom_number_8
FROM SUS_WK t JOIN
SC_PROD p
ON t.id = p.id;
I strongly recommend using the table alias for the UPDATE as well. SQL Server will resolve the table name to be the same as the t -- but depending on that makes the query rather hard to decipher (because references to the same table have difference aliases).

cannot insert value NULL into column error shows wrong column name

I've added a new column(NewValue) to my table which holds an int and allows nulls. Now I want to update the column but my insert statement only attempts to update the first column in the table not the one I specified.
I basically start with a temp table that I put my initial data into and it has two columns like this:
create table #tempTable
(
OldValue int,
NewValue int
)
I then do an insert into that table and based on the information NewValue can be null.
Example data in #tempTable:
OldValue NewValue
-------- --------
34556 8765432
34557 7654321
34558 null
Once that's complete I planned to insert NewValue into the primary table like so:
insert into myPrimaryTable(NewValue)
select tt.NewValue from #tempTable tt
left join myPrimaryTable mpt on mpt.Id = tt.OldValue
where tt.NewValue is not null
I only want the NewValue to insert into rows in myPrimaryTable where the Id matches the OldValue. However when I try to execute this code I get the following error:
Cannot insert the value NULL into column 'myCode', table 'myPrimaryTable'; column does not allow nulls. INSERT fails.
But I'm not trying to insert into 'myCode', I specified 'NewValue' as the column but it doesn't seem to see it. I've checked NewValue and it is set to allow int and is set to allow null and it does exist on the right table in the right database. The column 'myCode' is actually the second column in the table. Could someone please point me in the right direction with this error?
Thanks in advance.
INSERT always creates new rows, it never modifies existing rows. If you skip specifying a value for a column in an INSERT and that column has no DEFAULT bound to it and is not identity, that column will be NULL in the new row--thus your error. I believe you might be looking for an UPDATE instead of an INSERT.
Here's a potential query that might work for you:
UPDATE mpt
SET
mpt.NewValue = tt.NewValue
FROM
myPrimaryTable mpt
INNER JOIN #tempTable tt
ON mpt.Id = tt.OldValue -- really?
WHERE
tt.NewValue IS NOT NULL;
Note that I changed it to an INNER JOIN. A LEFT JOIN is clearly incorrect since you are filtering #tempTable for only rows with values, and don't want to update mpt where there is no match to tt--so LEFT JOIN expresses the wrong logical join type.
I put "really?" as a comment on the ON clause since I was wondering if OldValue is really an Id. It probably is--you know your table best. It just raised a mild red flag in my mind to see an Id column being compared to a column that does not have Id in its name (so if it is correct, I would suggest OldId as a better column choice than OldValue).
Also, I recommend that you never name a column just Id again--column names should be the same in every table in the database. Also, when it comes join time you will be more likely to make mistakes when your columns from different tables can coincide. It is much better to follow the format of SomethingId in the Something table, instead of just Id. Correspondingly, the suggested old column name would be OldSomethingId.

Inserting rows and updating rows on tables that may or may not have primary keys

I am trying to update a table so that rows that are missing are added and rows that are not up to date are updated using information from another table on a different database as a reference.
However, some tables have primary keys and some do not.
If there is a primary key the insert command will not run and if there is not a primary key, rows will duplicate.
Is there a way to have the insert command skip over primary key values that are already there?
I'm using sql server management studio 2005 and here is the code I have so far for a table with a primary key (PKcolumn):
INSERT [testDB].[dbo].[table1]
SELECT * FROM [sourceDB].[dbo].[table1]
UPDATE test
SET
test.[PKcolumn] = source.[PKcolumn]
,test.[column2] = source.[column2]
,test.[column3] = source.[column3]
FROM
[sourceDB].[dbo].[sourceDB] AS source
INNER JOIN
[testDB].[dbo].[PKcolumn] AS test
ON source.[PKcolumn] = test.[PKcolumn]
Update works perfectly but Insert will not run at all if there is even one duplicate.
Any suggestions on how to make this code work?
Also, any tips for doing the same thing on a table without a primary key?
You'll need to exclude rows that are already present in the table in your INSERT query, using a LEFT OUTER JOIN:
INSERT [testDB].[dbo].[table1]
SELECT * FROM [sourceDB].[dbo].[table1]
LEFT OUTER JOIN [testDB].[dbo].[table1] ON [sourceDB].[dbo].[table1].[PKcolumn] = [testDB].[dbo].[table1].[PKcolumn]
WHERE [testDB].[dbo].[table1].[PKcolumn] IS NULL
For a table without a primary key, I suppose you'd need to join on ALL columns to avoid duplicates.

SQL Server error 515

I have a table SINVOICE and another table called SINVOICE_LINE.
I need to put all columns of SINVOICE into SINVOICE_LINE.
I have created the corresponding columns and was trying to copy the values. The primary key of SINVOICE is SINVOICE_CODE, while the primary key for SINVOICE_LINE is a composite key (SINVOICE_CODE, SINVOICE_LINE_NUMBER).
I wrote the following query:
INSERT INTO SINVOICE_LINE (sinvoice.ITINERARY_CODE)
SELECT sinvoice_line.ITINERARY_CODE
FROM SINVOICE
INNER JOIN sinvoice_line ON sinvoice.sinvoice_code = sinvoice_line.sinvoice_code;
I get this error:
Cannot insert the value NULL into column SINVOICE_CODE, table SINVOICE_LINE; column does not allow nulls. INSERT fails.
I do not understand why I'm getting this error as I am not trying to insert any value in SINVOICE_CODE column.
Thanks!!!
Looks like you need UPDATE instead of INSERT here.
Try that:
UPDATE SINVOICE_LINE
SET ITINERARY_CODE = sinvoice.ITINERARY_CODE
from SINVOICE
WHERE sinvoice.sinvoice_code = sinvoice_line.sinvoice_code;

Create a unique primary key (hash) from database columns

I have this table which doesn't have a primary key.
I'm going to insert some records in a new table to analyze them and I'm thinking in creating a new primary key with the values from all the available columns.
If this were a programming language like Java I would:
int hash = column1 * 31 + column2 * 31 + column3*31
Or something like that. But this is SQL.
How can I create a primary key from the values of the available columns? It won't work for me to simply mark all the columns as PK, for what I need to do is to compare them with data from other DB table.
My table has 3 numbers and a date.
EDIT What my problem is
I think a bit more of background is needed. I'm sorry for not providing it before.
I have a database ( dm ) that is being updated everyday from another db ( original source ) . It has records form the past two years.
Last month ( july ) the update process got broken and for a month there was no data being updated into the dm.
I manually create a table with the same structure in my Oracle XE, and I copy the records from the original source into my db ( myxe ) I copied only records from July to create a report needed by the end of the month.
Finally on aug 8 the update process got fixed and the records which have been waiting to be migrated by this automatic process got copied into the database ( from originalsource to dm ).
This process does clean up from the original source the data once it is copied ( into dm ).
Everything look fine, but we have just realize that an amount of the records got lost ( about 25% of july )
So, what I want to do is to use my backup ( myxe ) and insert into the database ( dm ) all those records missing.
The problem here are:
They don't have a well defined PK.
They are in separate databases.
So I thought that If I could create a unique pk from both tables which gave the same number I could tell which were missing and insert them.
EDIT 2
So I did the following in my local environment:
select a.* from the_table#PRODUCTION a , the_table b where
a.idle = b.idle and
a.activity = b.activity and
a.finishdate = b.finishdate
Which returns all the rows that are present in both databases ( the .. union? ) I've got 2,000 records.
What I'm going to do next, is delete them all from the target db and then just insert them all s from my db into the target table
I hope I don't get in something worst : - S : -S
The danger of creating a hash value by combining the 3 numbers and the date is that it might not be unique and hence cannot be used safely as a primary key.
Instead I'd recommend using an autoincrementing ID for your primary key.
Just create a surrogate key:
ALTER TABLE mytable ADD pk_col INT
UPDATE mytable
SET pk_col = rownum
ALTER TABLE mytable MODIFY pk_col INT NOT NULL
ALTER TABLE mytable ADD CONSTRAINT pk_mytable_pk_col PRIMARY KEY (pk_col)
or this:
ALTER TABLE mytable ADD pk_col RAW(16)
UPDATE mytable
SET pk_col = SYS_GUID()
ALTER TABLE mytable MODIFY pk_col RAW(16) NOT NULL
ALTER TABLE mytable ADD CONSTRAINT pk_mytable_pk_col PRIMARY KEY (pk_col)
The latter uses GUID's which are unique across databases, but consume more spaces and are much slower to generate (your INSERT's will be slow)
Update:
If you need to create same PRIMARY KEYs on two tables with identical data, use this:
MERGE
INTO mytable v
USING (
SELECT rowid AS rid, rownum AS rn
FROM mytable
ORDER BY
co1l, col2, col3
)
ON (v.rowid = rid)
WHEN MATCHED THEN
UPDATE
SET pk_col = rn
Note that tables should be identical up to a single row (i. e. have same number of rows with same data in them).
Update 2:
For your very problem, you don't need a PK at all.
If you just want to select the records missing in dm, use this one (on dm side)
SELECT *
FROM mytable#myxe
MINUS
SELECT *
FROM mytable
This will return all records that exist in mytable#myxe but not in mytable#dm
Note that it will shrink all duplicates if any.
Assuming that you have ensured uniqueness...you can do almost the same thing in SQL. The only problem will be the conversion of the date to a numeric value so that you can hash it.
Select Table2.SomeFields
FROM Table1 LEFT OUTER JOIN Table2 ON
(Table1.col1 * 31) + (Table1.col2 * 31) + (Table1.col3 * 31) +
((DatePart(year,Table1.date) + DatePart(month,Table1.date) + DatePart(day,Table1.date) )* 31) = Table2.hashedPk
The above query would work for SQL Server, the only difference for Oracle would be in terms of how you handle the date conversion. Moreover, there are other functions for converting dates in SQL Server as well, so this is by no means the only solution.
And, you can combine this with Quassnoi's SET statement to populate the new field as well. Just use the left side of the Join condition logic for the value.
If you're loading your new table with values from the old table, and you then need to join the two tables, you can only "properly" do this if you can uniquely identify each row in the original table. Quassnoi's solution will allow you to do this, IF you can first alter the old table by adding a new column.
If you cannot alter the original table, generating some form of hash code based on the columns of the old table would work -- but, again, only if the hash codes uniquely identify each row. (Oracle has checksum functions, right? If so, use them.)
If hash code uniqueness cannot be guaranteed, you may have to settle for a primary key composed of as many columns are required to ensure uniqueness (e.g. the natural key). If there is no natural key, well, I heard once that Oracle provides a rownum for each row of data, could you use that?