On duplicate key update involving table to table insert - on-duplicate-key

I used the following script to populate a table. This script worked just fine:
insert into TSC_Intermediate.dbo.stock
(article
, description
, article_id
, client
, available_stock
, unit
, location
, warehouse)
select a.article
, b.art_descr
, a.article_id
, a.client
, a.value_1
, a.unit_code
, a.location
, a.warehouse
from aststock a
join
algarticle b
on a.client = b.client
and a.article = b.article
where a.client = 'cp'
Now what I need to do is continue to run that script but have it update available_stock when there is a duplicate key, and insert new rows when there is not. The key is on (article, location, warehouse)
I believe I need to use the code: ON DUPLICATE KEY UPDATE 'available_stock'
I'm missing something though. The other questions that I can see on this topic involve only adding 1 or 2 lines, so they specify what values to update. I'm confused as to how to make this work. Also, when I start typing ON DUPLICATE at the end of that code, SQL gives me a squiggly line under the ON, indicating that I'm putting it in the wrong place.

Answered my own question. Since I was using TSQL I had to use a merge statement.

Related

SQL-Server join issue when filtering on a freetext (vchar) column

I am stuck with a SQL Server view I am trying to create. The view returns a list of resources that are assigned to a project along with a few other details such as contract information.
I'm having issues with the resource_contracts table though because I'm stuck dealing with what is essentially a free-text field.
SELECT DISTINCT
CONCAT(RTRIM(res.first_name),' ', RTRIM(res.surname)) AS fullname ,
res.main_res_id ,
res.resource_id ,
res.resource_typ ,
res.status ,
rel.rel_value ,
asn.booking_project AS project ,
asn.booking_project_descr AS project_descr ,
asn.assignment_position AS position ,
asn.date_from AS commencement_date ,
DATEADD(DAY,1,asn.date_to) AS end_date ,
con.comment_fx
FROM resourcees res
INNER JOIN resource_relations rel
ON
res.main_res_id = rel.resource_id
AND rel.date_to >= CAST(CURRENT_TIMESTAMP AS DATE)
AND res.client = rel.client
LEFT OUTER JOIN resource_relations cc
ON
res.client = cc.client
AND res.resource_id = cc.resource_id
AND cc.rel_attr_id = 'C1'
AND res.date_to BETWEEN cc.date_from AND cc.date_to
AND cc.status = 'N'
INNER JOIN relation_values ar2
ON
cc.rel_value = ar2.dim_value
AND ar2.client = res.client
INNER JOIN assignments asn
ON
res.main_res_id = asn.resource_id
LEFT OUTER JOIN resource_contracts con
ON
con.dim_value = res.main_res_id
AND res.client = con.client
AND con.comment_fx LIKE '%CONAU%'
AND con.date_to_fx >= asn.date_to
WHERE
asn.booking_project = '123456'
ORDER BY
fullname
I guess the above looks fairly large. It's the last join causing the issue for reference.
The resource_contracts table contacts three columns. I hate this setup, but it's outside of my control unfortunately.
date_from_fx = DATETIME
date_to_fx = DATETIME
comment_fx = VCHAR 255
It's used to record contracts date from and date to, and a free text field that could contain anything annoyingly. Sample values might be "CONAU SPP" or "CONSG ABC" etc..
I'm stuck on the comment_fx field above however.
I specifically want to see contracts containing CONAU, or return a NULL value if they do not have one that meets the date require, or do not have a row at all. Unfortunately this logic is getting mixed up any other contract they have such as "CONSG ABC"
No matter what join I apply, I either can see all the resources with the contract required, or duplicate rows with null values and a mix of the non-applicable contracts. I guess I am missing something simple
Ultimately I need to produce a list of resources that are assigned to a project, but do not have the required contract (CONAU), that list will trigger another process that I've already sorted out.
Updated:
Let me show you the data that gets returned if we removed the resource_contracts table causing my issues:
Data result
Apologies, I couldn't format the table into something that resembled a table to paste here.
Here is the data from the contracts table:
contracts table
There's kind of multiple things I want to do here but I'll simplify it into a single one.
I'm trying to send a parameter to the query, 'CONAU' for example. So it will return all resources that do NOT have a valid row containing the string CONAU.
Problem is, they might have other rows like CONSG, or no rows at all.
During my attempts I would often get the wrong rows to show or when using ISNULL in the SELECT part, I would get null rows and duplicated data.
The conditions could be inverted but I'm trying to learn this myself.
SQL fiddle too: http://sqlfiddle.com/#!18/7558f/2
WHERE
asn.booking_project = '123456'
AND con.comment_fx LIKE '%CONAU%'
To the trailing end.

HANA SQL Script INSERT INTO with INNER JOIN can't insert values

I'm quite new to SQL and hope you can help me with my problem.
I have a table called Order_Status_Form_3 with the columns Order_ID (KEY), Customer_ID, Customer_Unique_ID, Status(KEY) and Date.
The table is filled, except for the Customer_Unique_ID Column.
To fill this Column I need to reference the Customer table where the Customer_ID is linked to the Customer_Unique_ID, so the right IDs cover the right places. When the Customer_ID in Order_Status_Form_3 equals the Customer_ID in the Customer table the given Customer_Unique_ID shall be inserted into the Customer_Unique_ID column in Order_Status_Form_3.
I tried to combine an INSERT INTO with a SELECT and INNER JOIN, but received an error message that says:
"cannot insert NULL or update to NULL: Order_ID".
I guess it's not clear for the program where to insert the values found and it tries to insert into all columns. I searched for similar problems but could not find any satisfying answers for my specific problem.
Here's the code I used:
Insert Into "HXE_109"."Order_Status_Form_3" ("Customer_Unique_ID")
Select customer."customer_unique_id"
From "HXE_109"."Customer" As customer
Inner Join "HXE_109"."Order_Status_Form_3" As OrderStatus3
On OrderStatus3."Customer_ID" = customer."customer_id"
I tried to specify the place to insert the values found by attaching a WHERE at the end, but received the same error.
Where OrderStatus3."Customer_ID" = customer."customer_id"
Does anyone know how to solve this issue and can tell me where my mistake is?
Thanks in advance for reading this long question and leaving an answer.
Edit
I tried using update but it seems like I cannot get it right.
Update "HXE_109"."Order_Status_Form_3"
Set "Customer_Unique_ID" = (Select customer."customer_unique_id"
From "HXE_109"."Customer" As customer
Inner Join "HXE_109"."Order_Status_Form_3" As OrderStatus3
On OrderStatus3."Customer_ID" = customer."customer_id")
Now I get the following error:
single row query returns more than one row
Do I need to use a Where condition here?
Sorry for my stupidity. :(
As I could follow the comments, what you want to do is running an UPDATE statement
Please check following DML command
Update "HXE_109"."Order_Status_Form_3"
Set
"Customer_Unique_ID" = customer."customer_unique_id"
From "HXE_109"."Order_Status_Form_3" As OrderStatus3
Inner Join "HXE_109"."Customer" As customer
On OrderStatus3."Customer_ID" = customer."customer_id"
If I try to explain the error messages:
"cannot insert NULL or update to NULL: Order_ID".
That is related with a field defined as NOT NULL. So in your target table ORDER_ID is defined as "not null", so in INSERT you have to provide a value for it or define it as an identity field in your HANA table definition
The second error: single row query returns more than one row
This is related with the case where SQL Engine expects a value not a set of values.
So the SELECT statement that you assign the results to Customer_Unique_ID field returns more than 1 value. In this case SQL engine raises an exception

A big 'like' matching query

I've got 2 tables,
'[Item] with field [name] nvarchar(255)
'[Transaction] with field [short_description] nvarchar(3999)
And I need to do thus :
Select [Transaction].id, [Item].id
From [Transaction] inner join [Item]
on [Transaction].[short_description] like ('%' + [Item].[name] + '%')
The above works if limited to a handful of items, but unfiltered is just going over 20 mins and I cancel.
I have a NC index on [name], but I cannot index [short_description] due to its length.
[Transaction] has 320,000 rows
[Items] has 42,000.
That's 13,860,000,000 combinations.
Is there a better way to perform this query ?
I did poke at full-text, but I'm not really that familiar, the answer was not jumping out at me there.
Any advice appreciated !!
Starting a comparison string with a wildcard (% or _) will NEVER use an index, and will typically be disastrous for performance. Your query will need to scan indexes rather than seek through them, so indexing won't help.
Ideally, you should have a third table that would allow a many-to-many relationship between Transaction and Item based on IDs. The design is the issue here.
After some more sleuthing I have utilized some Fulltext features.
sp_fulltext_keymappings
gives me my transaction table id, along with the FT docID
(I found out that 'doc' = text field)
sys.dm_fts_index_keywords_by_document
gives me FT documentId along with the individual keywords within it
Once I had that, the rest was simple.
Although, I do have to look into the term 'keyword' a bit more... seems that definition can be variable.
This only works because the text I am searching for has no white space.
I believe that you could tweak the FTI configuration to work with other scenarios... but I couldn't promise.
I need to look more into Fulltext.
My current 'beta' code below.
CREATE TABLE #keyMap
(
docid INT PRIMARY KEY ,
[key] varchar(32) NOT NULL
);
DECLARE #db_id int = db_id(N'<database name>');
DECLARE #table_id int = OBJECT_ID(N'Transactions');
INSERT INTO #keyMap
EXEC sp_fulltext_keymappings #table_id;
select km.[key] as transaction_id, i.[id] as item_id
from
sys.dm_fts_index_keywords_by_document ( #db_id, #table_id ) kbd
INNER JOIN
#keyMap km ON km.[docid]=kbd.document_id
inner join [items] i
on kdb.[display_term] = i.name
;
My actual version of the code includes inserting the data into a final table.
Execution time is coming in at 30 seconds, which serves my needs for now.

Select from two different tables and store calculated value in a newly created table (Microsoft SQL Server 2014)

What would be the best way to take values from two different tables like 1st table has the value of Price, where 2nd table has the value of Quantity, and I will multiply Price by Quantity and the calculated values, Total_Price which will be store in table 3 (newly created). At 1st I've tried using FUNCTION, but many error pops out, so I change it to CTE. But my teacher suggest me to not use temporary tables, because when new row data is added to the tables, we need to run the CTE again to update it everytime new record is added. Is there any other method? Thank you.
You can try something like (syntax not verified!):
INSERT INTO Table_3 (Cur_Date,Prod,Qty,Total_Price)
VALUES (GETDATE() ,
<the passed product_ID> ,
<the passed quantity> ,
(SELECT (A.Quantity * B.Price)
FROM Table_1 A ,
Table_2 B
WHERE A.Product = <Your passed product ID>
AND A.Product = B.Product
)
);
The actual phrasing will depend on your DBMS.

SQL Server : Select ... From with FULL JOIN with a Default value for a column

I created a table, tblNewParts with 3 columns:
NewCustPart
AddedDate
Handled
and I am trying to FULL JOIN it to an existing table, tblPartsWorkedOn.
tblNewParts is defined to have Handled defaulted to 'N'...
SELECT *
FROM dbo.tblPartsWorkedOn AS BASE
FULL JOIN dbo.tblNewParts AS ADDON ON BASE.[CustPN] = ADDON.[NewCustPart]
WHERE ADDON.[Handled] IS NULL
ORDER BY [CustPN] DESC
And I want the field [Handled] to come back as 'N' instead of NULL when I run the query. The problem is that when there aren't any records in the new table, I get NULL's instead of 'N's.
I saw a SELECT CASE WHEN col1 IS NULL THEN defaultval ELSE col1 END as a mostly suitable answer from here. I am wondering if this will work in this instance, and how would I write that in T-SQL for SQL Server 2012? I need all of the columns from both tables, rather than just the one.
I'm making this a question, rather than a comment on the cited link, so as to not obscure the original link's question.
Thank you for helping!
Name the column (alias.column_name) in select statement and use ISNULL(alias.column,'N').
Thanks
After many iterations I found the answer, it's kind of bulky but here it is anyway. Synopsis:
Yes, the CASE statement does work, but it gives the output as an unnamed column. Also, in this instance to get all of the original columns AND the corrected column, I had to use SELECT *, CASE...END as [ColumnName].
But, here is the better solution, as it will place the information into the correct column, rather than adding a column to the end of the table and calling that column 'Unnamed Column'.
Select [ID], [Seq], [Shipped], [InternalPN], [CustPN], [Line], [Status],
CASE WHEN ADDON.[NewCustPart] IS NULL THEN BASE.[CustPN] ELSE
ADDON.[NewCustomerPart] END as [NewCustPart],
GetDate() as [AddedDate],
CASE WHEN ADDON.[Handled] IS NULL THEN 'N' ELSE ADDON.[Handled] END as [Handled]
from dbo.tblPartsWorkedOn as BASE
full join dbo.tblNewParts as AddOn ON Base.[CustPN] = AddOn.NewCustPart
where AddOn.Handled = 'N' or AddOn.Handled is null
order by [NewCustPart] desc
This sql code places the [CustPN] into [NewCustPart] if it's null, it puts a 'N' into the field [Handled] if it's null and it assigns the date to the [AddedDate] field. It also only returns records that have not been handled, so that you get the ones that need to be looked at; and it orders the resulting output by the [NewCustPart] field value.
Resulting Output looks something like this: (I shortened the DateTime for the output here.)
[ID] [SEQ] [Shipped] [InternalPN] [CustPN] [Status] [NewCustPart] [AddedDate] [Handled]
1 12 N 10012A 10012A UP 10012A 04/02/2016 N
...
Rather than with the nulls:
[ID] [SEQ] [Shipped] [InternalPN] [CustPN] [Status] [NewCustPart] [AddedDate] [Handled]
1 12 N 10012A 10012A UP NULL NULL NULL
...
I'm leaving this up, and just answering it rather than deleting it, because I am fairly sure that someone else will eventually ask this same question. I think that lots of examples showing how and why something is done, is a very helpful thing to have as not everything can be generalized. Just some thoughts and I hope that this helps someone else!

Resources