Postgresql: Insert trigger function from select query, plus static values pulled from the new. ...
Why do some words that are not inflected have an umlaut?
Why is the maximum length of OpenWrt’s root password 8 characters?
slides for 30min~1hr skype tenure track application interview
Are spiders unable to hurt humans, especially very small spiders?
FPGA - DIY Programming
Reference request: Oldest number theory books with (unsolved) exercises?
Button changing it's text & action. Good or terrible?
Does a dangling wire really electrocute me if I'm standing in water?
Are there any other methods to apply to solving simultaneous equations?
Deal with toxic manager when you can't quit
A poker game description that does not feel gimmicky
Why is the Constellation's nose gear so long?
Time travel alters history but people keep saying nothing's changed
Pokemon Turn Based battle (Python)
How to answer pointed "are you quitting" questioning when I don't want them to suspect
Right tool to dig six foot holes?
Is there a symbol for a right arrow with a square in the middle?
What is the closest word meaning "respect for time / mindful"
Does coating your armor in silver add any effects?
Origin of "cooter" meaning "vagina"
Can you compress metal and what would be the consequences?
When should I buy a clipper card after flying to OAK?
Does the shape of a die affect the probability of a number being rolled?
Did 3000BC Egyptians use meteoric iron weapons?
Postgresql: Insert trigger function from select query, plus static values pulled from the new.
The 2019 Stack Overflow Developer Survey Results Are InPostgresql: Insert trigger function fails on partial insert statementWhy my BEFORE UPDATE trigger takes values from the NEW record?PostgreSQL trigger function that selects from %current% tableDisable/enable PostgreSQL trigger inside function for the same tablepostgresql insert from select query, plus static valuesPostgresql trigger update whole table after deleteCreate a trigger on all the last_modified columns in PostgreSQLmissing FROM-clause entry for table in trigger function in postgresqlGet result from select exists, execute insert query based on the response of itUse NEW in FROM clause in Postgres trigger?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
We're having an issue writing a trigger function that involves 3 tables: CustomerProfile, DropdownStats and OrderDetails. A simplified schema of each is as follows...
CustomerProfile table...this table has a row for all of the column names of the OrderDetails table.
CustID ColumnName IsDropDown
------ ---------- ----------
1 firstcolumn false
1 ...
1 orderid false
1 format false
1 department false
1 ...
1 lastcolumn false
DropdownStats table...
OrderID ColumnName ColumnValues CountOfColumnValues
------- ---------- ------------ -------------------
1 format circle 15
1 format square 23
1 format triangle 3
2 format circle 10
3 format square 5
3 format triangle 10
OrderDetails table...
firstcolumn ... orderid format department ... lastcolumn
----------- --- ------- ------ ---------- --- ----------
data dta 1 circle 123 dta data
data dta 1 square 134 dta data
...
data dta 2 circle 354 dta data
...
The trigger is written for the CustomerProfile table as an AFTER UPDATE trigger.
If the 4th row in the CustomerProfile table (where columnname = format) transitions the IsDropDown from false to true, then we have a to ADD rows to the DropdownStats table as they are pulled from the OrderDetails table.
The trigger function as written is producing results in the DropdownStats table like below but we want results like the sample above.
DropdownStats table...
OrderID ColumnName ColumnValues CountOfColumnValues
------- ---------- ------------ -------------------
1 format format 41
2 format format 10
3 format format 15
The problem is having the trigger function insert a static column name and then have a separate row for each of the distinct values found for that column and a count of rows that hold those values. Here is one (of several) attempt at this...the problem is the two new.columnname They should not be the same.
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select distinct
orderid
, new.columnname -- we want this to be the static actual name of the column, repeated for every record inserted (Ex: 'format')
, new.columnname -- we want a row for each of the values found for the column in the database (Ex: 'circle', 'square', 'triangle', etc.)
, count(new.columnname) -- the count of the records found for the value (Ex: for 'circle, count was 15)
from orderdetails
group by orderid, new.columnname;
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
If I just use the query tool and manually create and run the select statement shown below, I get what I want.
select distinct orderid, 'format', format, count(format) from orderdetails group by orderid, format;
But how do we translate the manual query into an equivalent trigger function? How do we distinguish the two "new.columnname" from each other?
postgresql trigger
bumped to the homepage by Community♦ 14 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
We're having an issue writing a trigger function that involves 3 tables: CustomerProfile, DropdownStats and OrderDetails. A simplified schema of each is as follows...
CustomerProfile table...this table has a row for all of the column names of the OrderDetails table.
CustID ColumnName IsDropDown
------ ---------- ----------
1 firstcolumn false
1 ...
1 orderid false
1 format false
1 department false
1 ...
1 lastcolumn false
DropdownStats table...
OrderID ColumnName ColumnValues CountOfColumnValues
------- ---------- ------------ -------------------
1 format circle 15
1 format square 23
1 format triangle 3
2 format circle 10
3 format square 5
3 format triangle 10
OrderDetails table...
firstcolumn ... orderid format department ... lastcolumn
----------- --- ------- ------ ---------- --- ----------
data dta 1 circle 123 dta data
data dta 1 square 134 dta data
...
data dta 2 circle 354 dta data
...
The trigger is written for the CustomerProfile table as an AFTER UPDATE trigger.
If the 4th row in the CustomerProfile table (where columnname = format) transitions the IsDropDown from false to true, then we have a to ADD rows to the DropdownStats table as they are pulled from the OrderDetails table.
The trigger function as written is producing results in the DropdownStats table like below but we want results like the sample above.
DropdownStats table...
OrderID ColumnName ColumnValues CountOfColumnValues
------- ---------- ------------ -------------------
1 format format 41
2 format format 10
3 format format 15
The problem is having the trigger function insert a static column name and then have a separate row for each of the distinct values found for that column and a count of rows that hold those values. Here is one (of several) attempt at this...the problem is the two new.columnname They should not be the same.
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select distinct
orderid
, new.columnname -- we want this to be the static actual name of the column, repeated for every record inserted (Ex: 'format')
, new.columnname -- we want a row for each of the values found for the column in the database (Ex: 'circle', 'square', 'triangle', etc.)
, count(new.columnname) -- the count of the records found for the value (Ex: for 'circle, count was 15)
from orderdetails
group by orderid, new.columnname;
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
If I just use the query tool and manually create and run the select statement shown below, I get what I want.
select distinct orderid, 'format', format, count(format) from orderdetails group by orderid, format;
But how do we translate the manual query into an equivalent trigger function? How do we distinguish the two "new.columnname" from each other?
postgresql trigger
bumped to the homepage by Community♦ 14 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
1
How often does the structure of OrderDetails change?
– RDFozz
Dec 14 '17 at 16:21
It does not change. It is very stable
– JoeDirt
Dec 14 '17 at 16:47
That makes the first of my two suggestions more reasonable (see below). Any time you'd add a new column toOrderDetails
, you'd have to update the trigger with anINSERT
using that specific column.
– RDFozz
Dec 14 '17 at 18:19
add a comment |
We're having an issue writing a trigger function that involves 3 tables: CustomerProfile, DropdownStats and OrderDetails. A simplified schema of each is as follows...
CustomerProfile table...this table has a row for all of the column names of the OrderDetails table.
CustID ColumnName IsDropDown
------ ---------- ----------
1 firstcolumn false
1 ...
1 orderid false
1 format false
1 department false
1 ...
1 lastcolumn false
DropdownStats table...
OrderID ColumnName ColumnValues CountOfColumnValues
------- ---------- ------------ -------------------
1 format circle 15
1 format square 23
1 format triangle 3
2 format circle 10
3 format square 5
3 format triangle 10
OrderDetails table...
firstcolumn ... orderid format department ... lastcolumn
----------- --- ------- ------ ---------- --- ----------
data dta 1 circle 123 dta data
data dta 1 square 134 dta data
...
data dta 2 circle 354 dta data
...
The trigger is written for the CustomerProfile table as an AFTER UPDATE trigger.
If the 4th row in the CustomerProfile table (where columnname = format) transitions the IsDropDown from false to true, then we have a to ADD rows to the DropdownStats table as they are pulled from the OrderDetails table.
The trigger function as written is producing results in the DropdownStats table like below but we want results like the sample above.
DropdownStats table...
OrderID ColumnName ColumnValues CountOfColumnValues
------- ---------- ------------ -------------------
1 format format 41
2 format format 10
3 format format 15
The problem is having the trigger function insert a static column name and then have a separate row for each of the distinct values found for that column and a count of rows that hold those values. Here is one (of several) attempt at this...the problem is the two new.columnname They should not be the same.
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select distinct
orderid
, new.columnname -- we want this to be the static actual name of the column, repeated for every record inserted (Ex: 'format')
, new.columnname -- we want a row for each of the values found for the column in the database (Ex: 'circle', 'square', 'triangle', etc.)
, count(new.columnname) -- the count of the records found for the value (Ex: for 'circle, count was 15)
from orderdetails
group by orderid, new.columnname;
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
If I just use the query tool and manually create and run the select statement shown below, I get what I want.
select distinct orderid, 'format', format, count(format) from orderdetails group by orderid, format;
But how do we translate the manual query into an equivalent trigger function? How do we distinguish the two "new.columnname" from each other?
postgresql trigger
We're having an issue writing a trigger function that involves 3 tables: CustomerProfile, DropdownStats and OrderDetails. A simplified schema of each is as follows...
CustomerProfile table...this table has a row for all of the column names of the OrderDetails table.
CustID ColumnName IsDropDown
------ ---------- ----------
1 firstcolumn false
1 ...
1 orderid false
1 format false
1 department false
1 ...
1 lastcolumn false
DropdownStats table...
OrderID ColumnName ColumnValues CountOfColumnValues
------- ---------- ------------ -------------------
1 format circle 15
1 format square 23
1 format triangle 3
2 format circle 10
3 format square 5
3 format triangle 10
OrderDetails table...
firstcolumn ... orderid format department ... lastcolumn
----------- --- ------- ------ ---------- --- ----------
data dta 1 circle 123 dta data
data dta 1 square 134 dta data
...
data dta 2 circle 354 dta data
...
The trigger is written for the CustomerProfile table as an AFTER UPDATE trigger.
If the 4th row in the CustomerProfile table (where columnname = format) transitions the IsDropDown from false to true, then we have a to ADD rows to the DropdownStats table as they are pulled from the OrderDetails table.
The trigger function as written is producing results in the DropdownStats table like below but we want results like the sample above.
DropdownStats table...
OrderID ColumnName ColumnValues CountOfColumnValues
------- ---------- ------------ -------------------
1 format format 41
2 format format 10
3 format format 15
The problem is having the trigger function insert a static column name and then have a separate row for each of the distinct values found for that column and a count of rows that hold those values. Here is one (of several) attempt at this...the problem is the two new.columnname They should not be the same.
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select distinct
orderid
, new.columnname -- we want this to be the static actual name of the column, repeated for every record inserted (Ex: 'format')
, new.columnname -- we want a row for each of the values found for the column in the database (Ex: 'circle', 'square', 'triangle', etc.)
, count(new.columnname) -- the count of the records found for the value (Ex: for 'circle, count was 15)
from orderdetails
group by orderid, new.columnname;
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
If I just use the query tool and manually create and run the select statement shown below, I get what I want.
select distinct orderid, 'format', format, count(format) from orderdetails group by orderid, format;
But how do we translate the manual query into an equivalent trigger function? How do we distinguish the two "new.columnname" from each other?
postgresql trigger
postgresql trigger
asked Dec 14 '17 at 15:56
JoeDirtJoeDirt
111
111
bumped to the homepage by Community♦ 14 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
bumped to the homepage by Community♦ 14 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
1
How often does the structure of OrderDetails change?
– RDFozz
Dec 14 '17 at 16:21
It does not change. It is very stable
– JoeDirt
Dec 14 '17 at 16:47
That makes the first of my two suggestions more reasonable (see below). Any time you'd add a new column toOrderDetails
, you'd have to update the trigger with anINSERT
using that specific column.
– RDFozz
Dec 14 '17 at 18:19
add a comment |
1
How often does the structure of OrderDetails change?
– RDFozz
Dec 14 '17 at 16:21
It does not change. It is very stable
– JoeDirt
Dec 14 '17 at 16:47
That makes the first of my two suggestions more reasonable (see below). Any time you'd add a new column toOrderDetails
, you'd have to update the trigger with anINSERT
using that specific column.
– RDFozz
Dec 14 '17 at 18:19
1
1
How often does the structure of OrderDetails change?
– RDFozz
Dec 14 '17 at 16:21
How often does the structure of OrderDetails change?
– RDFozz
Dec 14 '17 at 16:21
It does not change. It is very stable
– JoeDirt
Dec 14 '17 at 16:47
It does not change. It is very stable
– JoeDirt
Dec 14 '17 at 16:47
That makes the first of my two suggestions more reasonable (see below). Any time you'd add a new column to
OrderDetails
, you'd have to update the trigger with an INSERT
using that specific column.– RDFozz
Dec 14 '17 at 18:19
That makes the first of my two suggestions more reasonable (see below). Any time you'd add a new column to
OrderDetails
, you'd have to update the trigger with an INSERT
using that specific column.– RDFozz
Dec 14 '17 at 18:19
add a comment |
1 Answer
1
active
oldest
votes
Your problem is that your query is using new.columnname
to mean different things.
In the SELECT
list of the subquery, the first new.columnname
is intended to use the actual value stored new.columnname
. The second new.columnname
, the one in the COUNT()
and the one in the GROUP BY
are all intended not to be the literal value stored in new.columnname
, but a reference to the actual OrderDetails
column named in new.columnname
. In other words, the first is the string literal "format", while the second is the database column OrderDetails.format
.
Unfortunately, the engine will view each of new.columnname in the query as a string value "format", and will never interpret it as OrderDetails.format
.
There are at least two potential ways to get around this problem:
Explicit INSERT
s for each column
For each of the columns in OrderDetails
, write a separate INSERT
statement in your trigger:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
if new.columnname = 'first_column' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'first_column'
, first_column
, count(*)
from orderdetails
group by orderid, first_column;
elsif new.columnname = 'format' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'format'
, format
, count(*)
from orderdetails
group by orderid, format;
elsif ...
end;
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
(If there's special handling you want to do if new.columnname
doesn't match any of the values, you can use CASE ... WHEN ... ELSE ... END;
instead of IF ... THEN ... ELSIF ... THEN ... END;
, if you like.)
Dynamic SQL
Unless PostgreSQL has some restriction against it, you could use dynamic SQL to build the SQL statement you need each time through:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
EXECUTE format( 'insert into dropdownstats '
'(orderid,columnname,columnvalues,countofcolumnvalues) '
'select '
'orderid '
', %L '
', %I '
', count(*) '
'from orderdetails '
'group by orderid, %I '
,new.columnname, new.columnname, new.columnname);
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
CAVEATS: Code is untested, and PostgreSQL is not my primary SQL language, so I may have included typos or misunderstood some subtleties.
The Dynamic SQL looks like it will work better for us. The reason being that the first one was made using my abbreviated table structure. In actuality, there are 150+ columns on the table and it isn't practical to use the if-else structure. Of course you had no idea of that. I'm going to give the Dynamic a whirl and see if it can be pulled off in Postgres. Thank you!
– JoeDirt
Dec 14 '17 at 18:38
It's much easier to maintain, too. However, some people have a knee-jerk reaction to the phrase "dynamic SQL" (and, as I noted, I'm not really a PostgreSQL user, so it's possible that limits on what can happen in triggers might prevent this from working). Happy to try to help if you run into a snag, if I can.
– RDFozz
Dec 14 '17 at 18:48
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f193151%2fpostgresql-insert-trigger-function-from-select-query-plus-static-values-pulled%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your problem is that your query is using new.columnname
to mean different things.
In the SELECT
list of the subquery, the first new.columnname
is intended to use the actual value stored new.columnname
. The second new.columnname
, the one in the COUNT()
and the one in the GROUP BY
are all intended not to be the literal value stored in new.columnname
, but a reference to the actual OrderDetails
column named in new.columnname
. In other words, the first is the string literal "format", while the second is the database column OrderDetails.format
.
Unfortunately, the engine will view each of new.columnname in the query as a string value "format", and will never interpret it as OrderDetails.format
.
There are at least two potential ways to get around this problem:
Explicit INSERT
s for each column
For each of the columns in OrderDetails
, write a separate INSERT
statement in your trigger:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
if new.columnname = 'first_column' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'first_column'
, first_column
, count(*)
from orderdetails
group by orderid, first_column;
elsif new.columnname = 'format' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'format'
, format
, count(*)
from orderdetails
group by orderid, format;
elsif ...
end;
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
(If there's special handling you want to do if new.columnname
doesn't match any of the values, you can use CASE ... WHEN ... ELSE ... END;
instead of IF ... THEN ... ELSIF ... THEN ... END;
, if you like.)
Dynamic SQL
Unless PostgreSQL has some restriction against it, you could use dynamic SQL to build the SQL statement you need each time through:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
EXECUTE format( 'insert into dropdownstats '
'(orderid,columnname,columnvalues,countofcolumnvalues) '
'select '
'orderid '
', %L '
', %I '
', count(*) '
'from orderdetails '
'group by orderid, %I '
,new.columnname, new.columnname, new.columnname);
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
CAVEATS: Code is untested, and PostgreSQL is not my primary SQL language, so I may have included typos or misunderstood some subtleties.
The Dynamic SQL looks like it will work better for us. The reason being that the first one was made using my abbreviated table structure. In actuality, there are 150+ columns on the table and it isn't practical to use the if-else structure. Of course you had no idea of that. I'm going to give the Dynamic a whirl and see if it can be pulled off in Postgres. Thank you!
– JoeDirt
Dec 14 '17 at 18:38
It's much easier to maintain, too. However, some people have a knee-jerk reaction to the phrase "dynamic SQL" (and, as I noted, I'm not really a PostgreSQL user, so it's possible that limits on what can happen in triggers might prevent this from working). Happy to try to help if you run into a snag, if I can.
– RDFozz
Dec 14 '17 at 18:48
add a comment |
Your problem is that your query is using new.columnname
to mean different things.
In the SELECT
list of the subquery, the first new.columnname
is intended to use the actual value stored new.columnname
. The second new.columnname
, the one in the COUNT()
and the one in the GROUP BY
are all intended not to be the literal value stored in new.columnname
, but a reference to the actual OrderDetails
column named in new.columnname
. In other words, the first is the string literal "format", while the second is the database column OrderDetails.format
.
Unfortunately, the engine will view each of new.columnname in the query as a string value "format", and will never interpret it as OrderDetails.format
.
There are at least two potential ways to get around this problem:
Explicit INSERT
s for each column
For each of the columns in OrderDetails
, write a separate INSERT
statement in your trigger:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
if new.columnname = 'first_column' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'first_column'
, first_column
, count(*)
from orderdetails
group by orderid, first_column;
elsif new.columnname = 'format' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'format'
, format
, count(*)
from orderdetails
group by orderid, format;
elsif ...
end;
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
(If there's special handling you want to do if new.columnname
doesn't match any of the values, you can use CASE ... WHEN ... ELSE ... END;
instead of IF ... THEN ... ELSIF ... THEN ... END;
, if you like.)
Dynamic SQL
Unless PostgreSQL has some restriction against it, you could use dynamic SQL to build the SQL statement you need each time through:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
EXECUTE format( 'insert into dropdownstats '
'(orderid,columnname,columnvalues,countofcolumnvalues) '
'select '
'orderid '
', %L '
', %I '
', count(*) '
'from orderdetails '
'group by orderid, %I '
,new.columnname, new.columnname, new.columnname);
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
CAVEATS: Code is untested, and PostgreSQL is not my primary SQL language, so I may have included typos or misunderstood some subtleties.
The Dynamic SQL looks like it will work better for us. The reason being that the first one was made using my abbreviated table structure. In actuality, there are 150+ columns on the table and it isn't practical to use the if-else structure. Of course you had no idea of that. I'm going to give the Dynamic a whirl and see if it can be pulled off in Postgres. Thank you!
– JoeDirt
Dec 14 '17 at 18:38
It's much easier to maintain, too. However, some people have a knee-jerk reaction to the phrase "dynamic SQL" (and, as I noted, I'm not really a PostgreSQL user, so it's possible that limits on what can happen in triggers might prevent this from working). Happy to try to help if you run into a snag, if I can.
– RDFozz
Dec 14 '17 at 18:48
add a comment |
Your problem is that your query is using new.columnname
to mean different things.
In the SELECT
list of the subquery, the first new.columnname
is intended to use the actual value stored new.columnname
. The second new.columnname
, the one in the COUNT()
and the one in the GROUP BY
are all intended not to be the literal value stored in new.columnname
, but a reference to the actual OrderDetails
column named in new.columnname
. In other words, the first is the string literal "format", while the second is the database column OrderDetails.format
.
Unfortunately, the engine will view each of new.columnname in the query as a string value "format", and will never interpret it as OrderDetails.format
.
There are at least two potential ways to get around this problem:
Explicit INSERT
s for each column
For each of the columns in OrderDetails
, write a separate INSERT
statement in your trigger:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
if new.columnname = 'first_column' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'first_column'
, first_column
, count(*)
from orderdetails
group by orderid, first_column;
elsif new.columnname = 'format' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'format'
, format
, count(*)
from orderdetails
group by orderid, format;
elsif ...
end;
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
(If there's special handling you want to do if new.columnname
doesn't match any of the values, you can use CASE ... WHEN ... ELSE ... END;
instead of IF ... THEN ... ELSIF ... THEN ... END;
, if you like.)
Dynamic SQL
Unless PostgreSQL has some restriction against it, you could use dynamic SQL to build the SQL statement you need each time through:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
EXECUTE format( 'insert into dropdownstats '
'(orderid,columnname,columnvalues,countofcolumnvalues) '
'select '
'orderid '
', %L '
', %I '
', count(*) '
'from orderdetails '
'group by orderid, %I '
,new.columnname, new.columnname, new.columnname);
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
CAVEATS: Code is untested, and PostgreSQL is not my primary SQL language, so I may have included typos or misunderstood some subtleties.
Your problem is that your query is using new.columnname
to mean different things.
In the SELECT
list of the subquery, the first new.columnname
is intended to use the actual value stored new.columnname
. The second new.columnname
, the one in the COUNT()
and the one in the GROUP BY
are all intended not to be the literal value stored in new.columnname
, but a reference to the actual OrderDetails
column named in new.columnname
. In other words, the first is the string literal "format", while the second is the database column OrderDetails.format
.
Unfortunately, the engine will view each of new.columnname in the query as a string value "format", and will never interpret it as OrderDetails.format
.
There are at least two potential ways to get around this problem:
Explicit INSERT
s for each column
For each of the columns in OrderDetails
, write a separate INSERT
statement in your trigger:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
if new.columnname = 'first_column' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'first_column'
, first_column
, count(*)
from orderdetails
group by orderid, first_column;
elsif new.columnname = 'format' then
insert into dropdownstats
(orderid,columnname,columnvalues,countofcolumnvalues)
select
orderid
, 'format'
, format
, count(*)
from orderdetails
group by orderid, format;
elsif ...
end;
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
(If there's special handling you want to do if new.columnname
doesn't match any of the values, you can use CASE ... WHEN ... ELSE ... END;
instead of IF ... THEN ... ELSIF ... THEN ... END;
, if you like.)
Dynamic SQL
Unless PostgreSQL has some restriction against it, you could use dynamic SQL to build the SQL statement you need each time through:
if old.isdropdown <> new.isdropdown then --if there was a change
if new.isdropdown = true then --and the change was from false to true
EXECUTE format( 'insert into dropdownstats '
'(orderid,columnname,columnvalues,countofcolumnvalues) '
'select '
'orderid '
', %L '
', %I '
', count(*) '
'from orderdetails '
'group by orderid, %I '
,new.columnname, new.columnname, new.columnname);
else --the transition was from true to false
delete from dropdownstats as dd where dd.columnname = new.columnname;
end if;
end if;
CAVEATS: Code is untested, and PostgreSQL is not my primary SQL language, so I may have included typos or misunderstood some subtleties.
answered Dec 14 '17 at 18:09
RDFozzRDFozz
9,89731531
9,89731531
The Dynamic SQL looks like it will work better for us. The reason being that the first one was made using my abbreviated table structure. In actuality, there are 150+ columns on the table and it isn't practical to use the if-else structure. Of course you had no idea of that. I'm going to give the Dynamic a whirl and see if it can be pulled off in Postgres. Thank you!
– JoeDirt
Dec 14 '17 at 18:38
It's much easier to maintain, too. However, some people have a knee-jerk reaction to the phrase "dynamic SQL" (and, as I noted, I'm not really a PostgreSQL user, so it's possible that limits on what can happen in triggers might prevent this from working). Happy to try to help if you run into a snag, if I can.
– RDFozz
Dec 14 '17 at 18:48
add a comment |
The Dynamic SQL looks like it will work better for us. The reason being that the first one was made using my abbreviated table structure. In actuality, there are 150+ columns on the table and it isn't practical to use the if-else structure. Of course you had no idea of that. I'm going to give the Dynamic a whirl and see if it can be pulled off in Postgres. Thank you!
– JoeDirt
Dec 14 '17 at 18:38
It's much easier to maintain, too. However, some people have a knee-jerk reaction to the phrase "dynamic SQL" (and, as I noted, I'm not really a PostgreSQL user, so it's possible that limits on what can happen in triggers might prevent this from working). Happy to try to help if you run into a snag, if I can.
– RDFozz
Dec 14 '17 at 18:48
The Dynamic SQL looks like it will work better for us. The reason being that the first one was made using my abbreviated table structure. In actuality, there are 150+ columns on the table and it isn't practical to use the if-else structure. Of course you had no idea of that. I'm going to give the Dynamic a whirl and see if it can be pulled off in Postgres. Thank you!
– JoeDirt
Dec 14 '17 at 18:38
The Dynamic SQL looks like it will work better for us. The reason being that the first one was made using my abbreviated table structure. In actuality, there are 150+ columns on the table and it isn't practical to use the if-else structure. Of course you had no idea of that. I'm going to give the Dynamic a whirl and see if it can be pulled off in Postgres. Thank you!
– JoeDirt
Dec 14 '17 at 18:38
It's much easier to maintain, too. However, some people have a knee-jerk reaction to the phrase "dynamic SQL" (and, as I noted, I'm not really a PostgreSQL user, so it's possible that limits on what can happen in triggers might prevent this from working). Happy to try to help if you run into a snag, if I can.
– RDFozz
Dec 14 '17 at 18:48
It's much easier to maintain, too. However, some people have a knee-jerk reaction to the phrase "dynamic SQL" (and, as I noted, I'm not really a PostgreSQL user, so it's possible that limits on what can happen in triggers might prevent this from working). Happy to try to help if you run into a snag, if I can.
– RDFozz
Dec 14 '17 at 18:48
add a comment |
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f193151%2fpostgresql-insert-trigger-function-from-select-query-plus-static-values-pulled%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
How often does the structure of OrderDetails change?
– RDFozz
Dec 14 '17 at 16:21
It does not change. It is very stable
– JoeDirt
Dec 14 '17 at 16:47
That makes the first of my two suggestions more reasonable (see below). Any time you'd add a new column to
OrderDetails
, you'd have to update the trigger with anINSERT
using that specific column.– RDFozz
Dec 14 '17 at 18:19