I have an insert that is recording data from a webform and inserting it into my table. I'd like to run an update immediately after my insert that reads the previous insert and finds all the null fields and updates that record's null fields with a string of --
The data-type for all my fields is varchar
I have 20+ forms each with 100+ fields so i'm looking for a function that would be smart enough to read/update the fields that have null values without specifically enumerating/writing out each field for the update statement. This would just take way too long.
Does anyone know of a way to read simply which fields have null values and update any fields that are null to a string, in my case --
IF you can't alter your existing code,I would go with insert trigger...so after every insert,you can check and see the null values and update them like below
create trigger triggername
on table
after insert
as
begin
update t
set t.col1=isnull(i.col1,'--'),
t.col2=isnull(i.col2,'--')
rest of cols
from table t
join
inserted i
on i.matchingcol=t.mtachingcol
end
The issue with above approach is,you will have to check all inserted rows..I would go with this approach only,since filtering many cols with many or clauses is not good for performance
If is to just for display purposes,i would go with view
Instead of update after insert you may try changing table structure.
Set default value of the columns to --. If while insert no value is provided, -- will be inserted automatically.
Related
I am trying to insert extracted data from a sql table into a postgres table where the rows may or may not exist. If they do exist, I would like to set a specific column to its default (0)
The table is as
site_notes (
job_id text primary key,
attachment_id text,
complete int default 0);
My query is
INSERT INTO site_notes (
job_id,
attachment_id
)
VALUES
{jobs_sql}
ON CONFLICT (job_id) DO UPDATE
SET complete = DEFAULT;
However I am getting an error: psycopg2.errors.CardinalityViolation: ON CONFLICT DO UPDATE command cannot affect row a second time
HINT: Ensure that no rows proposed for insertion within the same command have duplicate constrained values.
Would anyone be able to advise on how to set the complete column to the default on event of a conflict ?
Many Thanks
An INSERT ... ON CONFLICT DO UPDATE statement (and indeed an UPDATE statement too) is not allowed to modify the same row more than once. It is not clear what {jobs_sql} in your question is, but it must contain several rows, and at least two of those have the same job_id.
Make sure that the same job_id does not occur more than once in the rows you want to INSERT.
Folks, I have the following table:
CREATE TABLE IF NOT EXISTS users(
userid CHAR(100) NOT NULL,
assetid text NOT NULL,
date timestamp NOT NULL,
PRIMARY KEY(userid, assetid)
);
After I run a few insert queries such as :
INSERT INTO users (userid, assetid, date) VALUES ( foo, bar, now() );
I would like to retrieve records in order they were stored in the database. However, i seem to be getting back records not in order.
How should I modify my retrieve statement?
SELECT * FROM users WHERE userid=foo;
I would like the result to be sorted in order things were stored :)
Thanks!
To expand on Mark's correct answer, PostgreSQL doesn't keep a row timestamp, and it doesn't keep rows in any particular order. Unless you define your tables with a column containing the timestamp they were inserted at, there is no way to select them in the order they were inserted.
PostgreSQL will often return them in the order they were inserted in anyway, but that's just because they happen to be in that order on the disk. This will change as you do updates on the table, or deletes then later inserts. Operations like vacuum full also change it. You should never, ever rely on the order without an explicit order by clause.
Also, if you want the insertion timestamp to differ for rows within a transaction you can use clock_timestamp instead of now(). Also, please use the SQL-standard current_timestamp instead of writing now().
Assuming your date column holds different timestamps for each item, by using the ORDER BY clause:
SELECT * FROM users WHERE userid=foo ORDER BY "date";
However, if you inserted a large number of records in a single transaction, the date column value will probably be the same for all of them - if so, there is no way to tell which was inserted first (from the information given).
We're in process of converting over from SQL Server to Postgres. I have a scenario that I am trying to accommodate. It involves inserting records from one table into another, WITHOUT listing out all of the columns. I realize this is not recommended practice, but let's set that aside for now.
drop table if exists pk_test_table;
create table public.pk_test_table
(
recordid SERIAL PRIMARY KEY NOT NULL,
name text
);
--example 1: works and will insert a record with an id of 1
insert into pk_test_table values(default,'puppies');
--example 2: fails
insert into pk_test_table
select first_name from person_test;
Error I receive in the second example:
column "recordid" is of type integer but expression is of type
character varying Hint: You will need to rewrite or cast the
expression.
The default keyword will tell the database to grab the next value.
Is there any way to utilize this keyword in the second example? Or some way to tell the database to ignore auto-incremented columns and just them be populated like normal?
I would prefer to not use a subquery to grab the next "id".
This functionality works in SQL Server and hence the question.
Thanks in advance for your help!
If you can't list column names, you should instead use the DEFAULT keyword, as you've done in the simple insert example. This won't work with a in insert into ... select ....
For that, you need to invoke nextval. A subquery is not required, just:
insert into pk_test_table
select nextval('pk_test_table_id_seq'), first_name from person_test;
You do need to know the sequence name. You could get that from information_schema based on the table name and inferring its primary key, using a function that takes just the table name as an argument. It'd be ugly, but it'd work. I don't think there's any way around needing to know the table name.
You're inserting value into the first column, but you need to add a value in the second position.
Therefore you can use INSERT INTO table(field) VALUES(value) syntax.
Since you need to fetch values from another table, you have to remove VALUES and put the subquery there.
insert into pk_test_table(name)
select first_name from person_test;
I hope it helps
I do it this way via a separate function- though I think I'm getting around the issue via the table level having the DEFAULT settings on a per field basis.
create table public.pk_test_table
(
recordid integer NOT NULL DEFAULT nextval('pk_test_table_id_seq'),
name text,
field3 integer NOT NULL DEFAULT 64,
null_field_if_not_set integer,
CONSTRAINT pk_test_table_pkey PRIMARY KEY ("recordid")
);
With function:
CREATE OR REPLACE FUNCTION func_pk_test_table() RETURNS void AS
$BODY$
INSERT INTO pk_test_table (name)
SELECT first_name FROM person_test;
$BODY$
LANGUAGE sql VOLATILE;
Then just execute the function via a SELECT FROM func_pk_test_table();
Notice it hasn't had to specify all the fields- as long as constraints allow it.
I have a database for saving various forms. I have a table of forms:
CREATE SEQUENCE seq_formtype;
CREATE TABLE formtype (
id_ft integer NOT NULL DEFAULT nextval('seq_formtype'),
name text
);
I have a table of different input fields in the form:
CREATE SEQUENCE seq_formstruct;
CREATE TABLE formstruct (
id_fs integer NOT NULL DEFAULT nextval('seq_formstruct'),
id_ft integer NOT NULL,
name text,
id_fstype text NOT NULL
);
And finally, I have a table in which I store the results from the form for each trial.
CREATE TABLE results (
id_trial integer NOT NULL,
id_fs integer NOT NULL,
res_value text
);
When I add the result, I want to check whether all inputs from formstruct were inserted - that means that there will be for each entry in formstruct where formtype = typ_trialu (pseudocode) an entry in results.
Now I am not even sure how to check it or where to start. My idea was to create a trigger that would check the consistency after insertion to results (ie after insertion of all inputfield results).
It could be done with trigger(s) after insert statements.
CREATE TRIGGER check_form_types_trigger
AFTER INSERT ON results
FOR EACH STATEMENT
EXECUTE PROCEDURE check_form_types_function();
And, in check_form_types_function (which should be plpgsql) you can raise an exception if your data (as a whole) are not consistent.
But, in the other hand, if you do this, you literally won't be able to insert partial data into results; you will be able to insert only whole data, with a single insert statement. And if you really care about consistency, you should do this check after each update & delete statements too.
Notes:
names like fs, ft, fstype are terrible, consider rename your columns.
consider using SERIALs (instead of just manually set up sequences)
consider using foreign keys
I am programming for iPhone and i am using SQLITE DB for my app.I have a situation where i want to insert records into the table,only if the records doesn't exist previously.Otherwise the records should not get inserted.
How can i do this?Please any body suggest me a suitable query for this.
Thank you one and all,
Looking at SQLite's INSERT page http://www.sqlite.org/lang_insert.html.
You can do it using the following syntax
INSERT OR IGNORE INTO tablename ....
Example
INSERT OR IGNORE INTO tablename(id, value, data) VALUES(2, 4562, 'Sample Data');
Note : You need to have a KEY on the table columns which uniquely identify a row. It is only if a duplicate KEY is tried to be inserted that INSERT OR IGNORE will not insert a new row.
In the above example if you have a KEY on id, then another row with id = 2 will not be inserted.
If you have a KEY only on id and value then a combination of id = 2 and value = 4562 will cause a new row not be inserted.
In short there must be a key to uniquely identify a ROW only then will the Database know there is a duplicate which SHOULD NOT Be allowed.
Otherwise if you do not have a KEY you would need to go the SELECT and then check if a row is already there, route. But here also whichever condition you are using on columns you can add them as a KEY to the table and simply use the INSERT OR IGNORE
In SQLite it is not possible to ALTER the table and add a constraint like UNIQUE or PRIMAY KEY. For that you need to recreate the table. Look at this FAQ on sqlite.org
http://sqlite.org/faq.html#q11
Hello Sankar what you can do is perform a select query with the record you wish to insert and then check the response via SQLite's SQLITE_NOTFOUND flag you can check whether that record already exists or not. If it doesn't exist you can insert it otherwise you skip inserting.
I hope this is helpful.