I have PostgreSQL DB table with 4 columns ex. col1, col2, col3, col4.
Col3 is unique indexed. I want to add new column with notNull and default value of col3 as after that I want to make newly created column also unique?
Is it possible to achieve this by simple Yii2 migration?
You cannot get what you want directly; the default expression cannot reference a another column. What you can do is make the new column unique but null-able, then update the values, and finally make the column not null. If needed you can create a trigger to maintain the new column. (see demo)
alter table a_table add new_col text unique;
update a_table set new_col = col3;
-- clean up any null values in new_col; (there is nothing saying
alter table a_table alter column new_col set not null;
If need long term the create a trigger function and trigger to manage new_col:
-- set new_col column
create or replace function new_col()
returns trigger
language plpgsql
as $$
begin
new.new_col = coalesce(new.new_col, new.col3, old.new_col, ''); -- always on update ???
return new;
end;
$$;
create trigger a_table_biur
before insert or update
on a_table
for each row execute function new_col();
The trigger function used the minimum logic necessary, and will not satisfy every condition. You will need to evaluate that.
I want to know if it's possible to do something like this on Postgres 11 in a trigger function.
CREATE OR REPLACE FUNCTION "searchs"."handle_content" ( )
RETURNS trigger
AS $BODY$
BEGIN
UPDATE table
set test = 1
WHERE item_id = NEW.format('%I_id',TG_TABLE_NAME);
END;
$BODY$
The primary key on table change, so i need to concat with the table name
NEW.format('%I_id',TG_TABLE_NAME)
I have solved with CASE, but I still wish to know if it's possible to convert to an array record type, or access it dynamic.
I have some operations in heavy rearanging data tables which goes good so far.
In one table with more than 50000 rows I have text column where text should be numbers only.
Now I would like to convert it to integer column.
So:
ALTER TABLE mytable ALTER COLUMN mycolumn TYPE integer;
That produces an error 42804: *datatype_mismatch*
By reading docs I find solution:
ALTER TABLE mytable ALTER COLUMN mycolumn TYPE integer USING (TRIM(mycolumn)::integer);
But I am aware that data may not be correct in mean of number order since this "masks" an error and there is possibility that column was edited (by hand). After all, maybe is only trailing space added or some other minor editing was made.
I have backup of data.
How would I find which exact cell of given column contain an error and which value cannot be casted to int with some handy query suitable for use from pgadmin?
Please that query if is not complicated too much.
Expanding on #dystroy's answer, this query should cough the precise value of any offending rows:
CREATE OR REPLACE FUNCTION convert_to_integer(v_input text)
RETURNS INTEGER AS $$
BEGIN
BEGIN
RETURN v_input::INTEGER;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION 'Invalid integer value: "%". Returning NULL.', v_input;
RETURN NULL;
END;
END;
$$ LANGUAGE plpgsql;
Original answer:
If the following works:
ALTER TABLE mytable
ALTER COLUMN mycolumn TYPE integer USING (TRIM(mycolumn)::integer);
Then you should probably be able to run the following to locate the trash:
select mycolumn from mytable
where mycolumn::text <> (TRIM(mycolumn)::integer)::text;
TRIGEER-->To get a column value from one table to other table when i insert values?
I am having two tables(customer_details and loan_balance).
What i need is, I must get the column (custid)of customer_details table to the loan_balance table when i insert the data into the loan_balance table.
This is the full set up of my query : SQL FIDDLE
So i need a trigger to be raised and the data should be updated automatically without dynamic insertion of custid.
Postgres has an unconventional way of creating triggers:
create a function that returns type trigger and return the NEW row record
create a trigger that executes the function
Here's the code you need:
CREATE FUNCTION synch_custid_proc()
RETURNS trigger AS $$
BEGIN
NEW.custid = (
select max(custid)
from customer_details
where creditid = NEW.creditid
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql
CREATE TRIGGER synch_custid_trig
BEFORE INSERT ON loan_amount
FOR EACH ROW
EXECUTE PROCEDURE synch_custid_proc();
I chosen to select max(custid) rather than simply custid when finding the value in case there are multiple rows that match. You might have to adjust this logic to suit your data.
See a live demo on SQLFiddle
I am trying to delete a row from one table and insert it with some additional data into another. I know this can be done in two separate commands, one to delete and another to insert into the new table. However I am trying to combine them and it is not working, this is my query so far:
insert into b (one,two,num) values delete from a where id = 1 returning one, two, 5;
When running that I get the following error:
ERROR: syntax error at or near "delete"
Can anyone point out how to accomplish this, or is there a better way? or is it not possible?
You cannot do this before PostgreSQL 9.1, which is not yet released. And then the syntax would be
WITH foo AS (DELETE FROM a WHERE id = 1 RETURNING one, two, 5)
INSERT INTO b (one, two, num) SELECT * FROM foo;
Before PostgreSQL 9.1 you can create a volatile function like this (untested):
create function move_from_a_to_b(_id integer, _num integer)
returns void language plpgsql volatile as
$$
declare
_one integer;
_two integer;
begin
delete from a where id = _id returning one, two into strict _one, _two;
insert into b (one,two,num) values (_one, _two, _num);
end;
$$
And then just use select move_from_a_to_b(1, 5). A function has the advantage over two statements that it will always run in single transaction — there's no need to explicitly start and commit transaction in client code.
For all version of PostgreSQL, you can create a trigger function for deleting rows from a table and inserting them to another table. But it seems slower than bulk insert that is released in PostgreSQL 9.1. You just need to move the old data into the another table before it gets deleted. This is done with the OLD data type:
CREATE FUNCTION moveDeleted() RETURNS trigger AS $$
BEGIN
INSERT INTO another_table VALUES(OLD.column1, OLD.column2,...);
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER moveDeleted
BEFORE DELETE ON table
FOR EACH ROW
EXECUTE PROCEDURE moveDeleted();
As above answer, after PostgreSQL 9.1 you can do this:
WITH tmp AS (DELETE FROM table RETURNING column1, column2, ...)
INSERT INTO another_table (column1, column2, ...) SELECT * FROM tmp;
That syntax you have there isn't valid. 2 statements is the best way to do this. The most intuitive way to do it would be to do the insert first and the delete second.
As "AI W", two statements are certainly the best option for you, but you could also consider writing a trigger for that. Each time something is deleted in your first table, another is filled.