PostgresSQL Copy a row to the same table and alter one value - postgresql

I want to insert a new row which copies the two fields from the original row, and changes the last field to a new value. This is all done on one table.
Please excuse the table names/fields, they are very long.
Table 1 - alert_template_allocations
alert_template_allocation_id - pkey (ignored)
alert_template_allocation_io_id - (copy)
alert_template_allocation_alert_template_id - (copy)
alert_template_allocation_user_group_id - (change to a static value)
Table 2 - io
io_id - copy io_ids that belong to station 222
io_station_id - want to only copy rows where the station id = 222
My Attempt
insert into alert_template_allocations
(alert_template_allocation_io_id,
alert_template_allocation_alert_template_id,
alert_template_allocation_user_group_id)
values
(
(Select at.alert_template_allocation_io_id,
at.alert_template_allocation_alert_template_id
from alert_template_allocations at join io i on
i.io_id = at.alert_template_allocation_io_id
and i.io_station_id = 222)
, 4);

Use INSERT INTO SELECT syntax:
INSERT INTO alert_template_allocations (alert_template_allocation_io_id,
alert_template_allocation_alert_template_id,
alert_template_allocation_user_group_id)
SELECT at.alert_template_allocation_io_id,
at.alert_template_allocation_alert_template_id,
4
FROM alert_template_allocations at
JOIN io i
ON i.io_id = at.alert_template_allocation_io_id
AND i.io_station_id = 222;

Related

DB2 Query : insert data in history table if not exists already

I have History table and transaction table.....and reference table...
If status in reference table is CLOSE then take those record verify in History table if not there insert from transaction table..... wiring query like this .... checking better one... please advice.. this query can be used for huge data ?
INSERT INTO LIB1.HIST_TBL
( SELECT R.ACCT, R.STATUS, R.DATE FROM
LIB2.HIST_TBL R JOIN LIB1.REF_TBL C
ON R.ACCT = C.ACCT WHERE C.STATUS = '5'
AND R.ACCT NOT IN
(SELECT ACTNO FROM LIB1.HIST_TBL)) ;
If you're on a current release of DB2 for i, take a look at the MERGE statement
MERGE INTO hist_tbl H
USING (SELECT * FROM ref_tbl R
WHERE r.status = 'S')
ON h.actno = r.actno
WHEN NOT MATCHED THEN
INSERT (actno,histcol2, histcol3) VALUES (r.actno,r.refcol2,r.refcol3)
--if needed
WHEN MATCHED
UPDATE SET (actno,histcol2, histcol3) = (r.actno,r.refcol2,r.refcol3)

Cannot insert NULL value into column error

I have a issue where I want to update a column in a table and with a trigger to update same column but in another table. It says I cannot insert NULL but I can't seem to understand from where it gets that NULL value. This is the trigger:
CREATE TRIGGER Custom_WF_Update_WF_DefinitionSteps_DefinitionId ON WF.Definition
AFTER UPDATE AS BEGIN
IF UPDATE(DefinitionId)
IF TRIGGER_NESTLEVEL() < 2
BEGIN
ALTER TABLE WF.DefinitionSteps NOCHECK CONSTRAINT ALL
UPDATE WF.DefinitionSteps
SET DefinitionId =
(SELECT i.DefinitionId
FROM inserted i,
deleted d
WHERE WF.DefinitionSteps.DefinitionId = d.DefinitionId
AND i.oldPkCol = d.DefinitionId)
WHERE WF.DefinitionSteps.DefinitionId IN
(SELECT DefinitionId FROM deleted)
ALTER TABLE WF.DefinitionSteps CHECK CONSTRAINT ALL
END
END
This update statement works just fine:
UPDATE [CCHMergeIntermediate].[WF].[Definition]
SET DefinitionId = source.DefinitionId + 445
FROM [CCHMergeIntermediate].[WF].[Definition] source
But this one fails:
UPDATE [CCHMergeIntermediate].[WF].[Definition]
SET DefinitionId = target.DefinitionId
FROM [CCHMergeIntermediate].[WF].[Definition] source
INNER JOIN [centralq3].[WF].[Definition] target
ON (((source.Name = target.Name) OR (source.Name IS NULL AND target.Name IS NULL)))
I get the following error:
Msg 515, Level 16, State 2, Procedure Custom_WF_Update_WF_DefinitionSteps_DefinitionId, Line 7
Cannot insert the value NULL into column 'DefinitionId', table 'CCHMergeIntermediate.WF.DefinitionSteps'; column does not allow nulls. UPDATE fails.
If I do a select instead of the update statement, like this:
SELECT source.DefinitionId, target.DefinitionId
FROM [CCHMergeIntermediate].[WF].[Definition] source
INNER JOIN [centralq3].[WF].[Definition] target
ON (((source.Name = target.Name) OR (source.Name IS NULL AND target.Name IS NULL)))
I get this result:
http://i.stack.imgur.com/3cZsM.png (sorry for external link, I don't have enaugh reputation to post image here )
What am I doing wrong? What I don't see? What am I missing..?
The problem was in the trigger at the condition. I modified the second where from i.oldPkCol = d.DefinitionId to i.oldPkCol = **d.oldPkCol** and it worked.
UPDATE WF.DefinitionSteps
SET DefinitionId =
(SELECT i.DefinitionId
FROM inserted i,
deleted d
WHERE WF.DefinitionSteps.DefinitionId = d.DefinitionId
AND i.oldPkCol = **d.oldPkCol**)
WHERE WF.DefinitionSteps.DefinitionId IN
(SELECT DefinitionId FROM deleted)

Inserting values into multiple columns by splitting a string in PostgreSQL

I have the following heap of text:
"BundleSize,155648,DynamicSize,204800,Identifier,com.URLConnectionSample,Name,
URLConnectionSample,ShortVersion,1.0,Version,1.0,BundleSize,155648,DynamicSize,
16384,Identifier,com.IdentifierForVendor3,Name,IdentifierForVendor3,ShortVersion,
1.0,Version,1.0,".
What I'd like to do is extract data from this in the following manner:
BundleSize:155648
DynamicSize:204800
Identifier:com.URLConnectionSample
Name:URLConnectionSample
ShortVersion:1.0
Version:1.0
BundleSize:155648
DynamicSize:16384
Identifier:com.IdentifierForVendor3
Name:IdentifierForVendor3
ShortVersion:1.0
Version:1.0
All tips and suggestions are welcome.
It isn't quite clear what do you need to do with this data. If you really need to process it entirely in the database (looks like the task for your favorite scripting language instead), one option is to use hstore.
Converting records one by one is easy:
Assuming
%s =
BundleSize,155648,DynamicSize,204800,Identifier,com.URLConnectionSample,Name,URLConnectionSample,ShortVersion,1.0,Version,1.0
SELECT * FROM each(hstore(string_to_array(%s, ',')));
Output:
key | value
--------------+-------------------------
Name | URLConnectionSample
Version | 1.0
BundleSize | 155648
Identifier | com.URLConnectionSample
DynamicSize | 204800
ShortVersion | 1.0
If you have table with columns exactly matching field names (note the quotes, populate_record is case-sensitive to key names):
CREATE TABLE data (
"BundleSize" integer, "DynamicSize" integer, "Identifier" text,
"Name" text, "ShortVersion" text, "Version" text);
You can insert hstore records into it like this:
INSERT INTO data SELECT * FROM
populate_record(NULL::data, hstore(string_to_array(%s, ',')));
Things get more complicated if you have comma-separated values for more than one record.
%s = BundleSize,155648,DynamicSize,204800,Identifier,com.URLConnectionSample,Name,URLConnectionSample,ShortVersion,1.0,Version,1.0,BundleSize,155648,DynamicSize,16384,Identifier,com.IdentifierForVendor3,Name,IdentifierForVendor3,ShortVersion,1.0,Version,1.0,
You need to break up an array into chunks of number_of_fields * 2 = 12 elements first.
SELECT hstore(row) FROM (
SELECT array_agg(str) AS row FROM (
SELECT str, row_number() OVER () AS i FROM
unnest(string_to_array(%s, ',')) AS str
) AS str_sub
GROUP BY (i - 1) / 12) AS row_sub
WHERE array_length(row, 1) = 12;
Output:
"Name"=>"URLConnectionSample", "Version"=>"1.0", "BundleSize"=>"155648", "Identifier"=>"com.URLConnectionSample", "DynamicSize"=>"204800", "ShortVersion"=>"1.0"
"Name"=>"IdentifierForVendor3", "Version"=>"1.0", "BundleSize"=>"155648", "Identifier"=>"com.IdentifierForVendor3", "DynamicSize"=>"16384", "ShortVersion"=>"1.0"
And inserting this into the aforementioned table:
INSERT INTO data SELECT (populate_record(NULL::data, hstore(row))).* FROM ...
the rest of the query is the same.

splitting a string and rebuilding from related data

I've been given a string that can contain multiple offer codes separated by a tilde 123~125~126
I also have a table that may or may not define a parent/child relationship
tbl_allowed
============
offercode varchar(15)
parent_oc varchar(15)
ex:
offercode = 124
parent_oc = 126
I already have a function that will take the delimited string and split it, but I want to take the string, compare the contents to what's in tbl_allowed and regenerate it by replacing any values that exist in tbl_allowed in the parent_oc column with the value in the offercode column. If no defined relationship exists, then just use itself.
this is pretty simple with a single offercode:
set #newOfferCode = (select top 1 coalesce(cac.offercode, #lOfferCode)
from tbl_allowed cac
where OfferCode = #lOfferCode or parent_oc = #lOfferCode)
select coalesce(nullif(#newOfferCode,''), #lOfferCode)
but I'm having difficulty when I have a tilde delimited string. Any ideas?
Here's what I ended up doing. Seems to work.
CREATE TABLE #tempoffers(OfferCode varchar(15), NewOfferCode varchar(15))
INSERT INTO #tempoffers
SELECT OutParam, null
FROM dbo.SplitString(#lOfferCode, '~')
update #tempoffers set NewOfferCode = coalesce(cac.offercode, mb.offerCode)
from #tempoffers mb
left outer join tbl_Allowed cac on mb.OfferCode = cac.parent_oc
-- building the new string
declare #newOfferCode varchar(5000)
SELECT #newOfferCode = COALESCE(#newOfferCode + '~', '') + NewOfferCode FROM #tempoffers
drop table #tempoffers
SELECT #newOfferCode as OfferCode

Inserting many rows in treelike structure in SQL SERVER 2005

I have a few tables in SQL that are pretty much like this
A B C
ID_A ID_B ID_C
Name Name Name
ID_A ID_B
As you can see, A is linked to B and B to C. Those are basically tables that contains data models. Now, I would need to be able to create date based on those tables. For example, if I have the following datas
A B C
1 Name1 1 SubName1 1 1 SubSubName1 1
2 Name2 2 SubName2 1 2 SubSubName2 1
3 SubName3 2 3 SubSubName3 2
4 SubSubName4 3
5 SubSubName5 3
I would like to copy the 'content' of those tables in others tables. Of course, the auto numeric key that is generated when inserting into the new tables are diffirent that those one and I would like to be able to keep track so that I can copy the entire thing. The structure of the recipient table contains more information that those, but it's mainly dates and other stuff that are easy to get for me.
I would need to this entirely in TRANSACT-SQL (with built-in function if needed). Is this possible and can anyone give me a short example. I manage to do it for one level, but I get confused for the rest.
thanks
EDIT : The info above is just an example, because my actual diagram looks more like this
Model tables :
Processes -- (1-N) Steps -- (1-N) Task -- (0-N) TaskCheckList
-- (0-N) StepsCheckLists
Where as the table I need to fill looks like this
Client -- (0-N) Sequence -- (1-N) ClientProcesses -- (1-N) ClientSteps -- (1-N)ClientTasks -- (0-N) ClientTaskCheckList
-- (0-N)ClientStepCheckLists
The Client already exists and when I need to run the script, I create one sequence, which will contains all processes, which will contains its steps, taks, etc...
Ok,
So I did a lot of trials and error, and here is what I got. It seems to work fine although it sound quite big for something that seemed easy at first.
The whole this is somehow in french and english because our client is french and so are we anyway. It does insert every date in all tables that I needed. The only thing left to this will be the first lines where I need to select the date to insert according to some parameters but this is the easy part.
DECLARE #IdProcessusRenouvellement bigint
DECLARE #NomProcessus nvarchar(255)
SELECT #IdProcessusRenouvellement = ID FROM T_Ref_Processus WHERE Nom LIKE 'EXP%'
SELECT #NomProcessus = Nom FROM T_Ref_Processus WHERE Nom LIKE 'EXP%'
DECLARE #InsertedSequence table(ID bigint)
DECLARE #Contrats table(ID bigint,IdClient bigint,NumeroContrat nvarchar(255))
INSERT INTO #Contrats SELECT ID,IdClient,NumeroContrat FROM T_ClientContrat
DECLARE #InsertedIdsSeq as Table(ID bigint)
-- Séquences de travail
INSERT INTO T_ClientContratSequenceTravail(IdClientContrat,Nom,DateDebut)
OUTPUT Inserted.ID INTO #InsertedIdsSeq
SELECT ID, #NomProcessus + ' - ' + CONVERT(VARCHAR(10), GETDATE(), 120) + ' : ' + NumeroContrat ,GETDATE()
FROM #Contrats
-- Processus
DECLARE #InsertedIdsPro as Table(ID bigint,IdProcessus bigint)
INSERT INTO T_ClientContratProcessus
(IdClientContratSequenceTravail,IdProcessus,Nom,DateDebut,DelaiRappel,DateRappel,LienAvecPro cessusRenouvellement,IdStatutProcessus,IdResponsable,Sequence)
OUTPUT Inserted.ID,Inserted.IdProcessus INTO #InsertedIdsPro
SELECT I.ID,P.ID,P.Nom,GETDATE(),P.DelaiRappel,GETDATE(),P.LienAvecProcessusRenouvellement,0,0,0
FROM #InsertedIdsSeq I, T_Ref_Processus P
WHERE P.ID = #IdProcessusRenouvellement
-- Étapes
DECLARE #InsertedIdsEt as table(ID bigint,IdProcessusEtape bigint)
INSERT INTO T_ClientContratProcessusEtape
(IdClientContratProcessus,IdProcessusEtape,Nom,DateDebut,DelaiRappel,DateRappel,NomListeVeri fication,Sequence,IdStatutEtape,IdResponsable,IdTypeResponsable,ListeVerificationTermine)
OUTPUT Inserted.ID,Inserted.IdProcessusEtape INTO #InsertedIdsEt
SELECT I.ID,E.ID,
E.Nom,GETDATE(),E.DelaiRappel,GETDATE(),COALESCE(L.Nom,''),E.Sequence,0,0,E.IdTypeResponsabl e,0
FROM #InsertedIdsPro I INNER JOIN T_Ref_ProcessusEtape E ON I.IdProcessus = E.IdProcessus
LEFT JOIN T_Ref_ListeVerification L ON E.IdListeVerification = L.ID
-- Étapes : Items de la liste de vérification
INSERT INTO T_ClientContratProcessusEtapeListeVerificationItem
(IdClientContratProcessusEtape,Nom,Requis,Verifie)
SELECT I.ID,IT.Nom,IT.Requis,0
FROM #InsertedIdsEt I
INNER JOIN T_Ref_ProcessusEtape E ON I.IdProcessusEtape = E.ID
INNER JOIN T_Ref_ListeVerificationItem IT ON E.IdListeVerification = IT.IdListeVerification
-- Tâches
DECLARE #InsertedIdsTa as table(ID bigint, IdProcessusEtapeTache bigint)
INSERT INTO T_ClientContratProcessusEtapeTache
(IdClientContratProcessusEtape,IdProcessusEtapeTache,Nom,DateDebut,DelaiRappel,DateRappel,No mListeVerification,Sequence,IdStatutTache,IdResponsable,IdTypeResponsable,ListeVerificationT ermine)
OUTPUT Inserted.ID,Inserted.IdProcessusEtapeTache INTO #InsertedIdsTa
SELECT I.ID,T.ID,
T.Nom,GETDATE(),T.DelaiRappel,GETDATE(),COALESCE(L.Nom,''),T.Sequence,0,0,T.IdTypeResponsabl e,0
FROM #InsertedIdsEt I
INNER JOIN T_Ref_ProcessusEtapeTache T ON I.IdProcessusEtape = T.IdProcessusEtape
LEFT JOIN T_Ref_ListeVerification L ON T.IdListeVerification = L.ID
-- Tâches : Items de la liste de vérification
INSERT INTO T_ClientContratProcessusEtapeTacheListeVerificationItem
(IdClientContratProcessusEtapeTache,Nom,Requis,Verifie)
SELECT I.ID,IT.Nom,IT.Requis,0
FROM #InsertedIdsTa I
INNER JOIN T_Ref_ProcessusEtapeTache T ON I.IdProcessusEtapeTache = T.ID
INNER JOIN T_Ref_ListeVerificationItem IT ON T.IdListeVerification = IT.IdListeVerification