How to add comparing to ON CONFLICT () DO UPDATE - sql

I need to check, if in table there are any operations with current user for today.
Usually I compare time in this way: timestamp > CURRENT_TIMESTAMP::date
Could you please help, how to do it in INSERT in ON CONFLICT () DO UDPATE?
INSERT INTO table (login, smth, timestamp)
VALUES ('username', 'smth', CURRENT_TIMESTAMP)
ON CONFLICT (login, timestamp) DO UPDATE
SET smth = 'smth'
timestamp = CURRENT_TIMESTAMP
Here will be exactly comparing of timestamp, but I need to check, if it's for today, like above: timestamp > CURRENT_TIMESTAMP::date
Thanks!

If you want to store the timestamp but have a unique constraint on the date, then you can do that easily in the most recent versions of Postgres using a computed column. This requires adding a new column which is the date into the table:
create table t (
login text,
smth text,
ts timestamp,
ts_date date generated always as (ts::date) stored
);
And then creating a unique constraint:
create unique index unq_t_login_timestamp on t(login, ts_date);
Now you can use on conflict:
INSERT INTO t (login, smth, ts)
VALUES ('username', 'smth', CURRENT_TIMESTAMP)
ON CONFLICT (login, ts_date) DO UPDATE
SET smth = 'smth',
ts = CURRENT_TIMESTAMP;
Here is the code in a db<>fiddle.
EDIT:
It is better to eschew the computed column and just use:
create unique index unq_t_login_timestamp on t(login, (timestamp::date));

If you can use CTE, see here.
In case of your question, the query is like below:
(However, I'm not clear what "timestamp > CURRENT_TIMESTAMP::date" means.)
with
"data"("w_login","w_smth","w_timestamp") as (
select 'username2'::text, 'smth'::text, CURRENT_TIMESTAMP
),
"update" as (
update "table" set ("smth","timestamp")=("w_smth","w_timestamp") from "data"
where "login"="w_login" and "w_timestamp">CURRENT_TIMESTAMP::date
returning *
)
insert into "table"
select * from "data"
where not exists (select * from "update");
DB Fiddle

Related

Recreate table from a select and add an extra datetime default column (Snowflake)

I'm having problems creating a table that should be pretty straightforward. The SQL code (Snowflake) is:
create or replace table bank_raw as
select
*,
created_at datetime default current_timestamp()
from bank_raw;
My error is: Syntax error: unexpected 'DEFAULT'. (line 12).
I don't know how I can recreate this table and add this default timestamp column. By the way, I have already created multiple tables from scratch with created_at DateTime default current_timestamp().
Any ideas?
It is possible to define column list definition when using CTAS:
Sample data:
CREATE TABLE bank_raw(id INT, col TEXT);
INSERT INTO bank_raw(id, col) VALUES (1, 'a'), (2,'b');
Query:
CREATE OR REPLACE TABLE bank_raw(id INT,
col TEXT,
created_at datetime default current_timestamp())
AS
SELECT
id, col, CURRENT_TIMESTAMP()
FROM bank_raw;
Output:
SELECT * FROM bank_raw;
DESCRIBE TABLE bank_raw;
Since this is a DML operation not a DDL operation, the default keyword does not apply. You can simply remove it and instead project the column and name it:
create or replace table bank_raw as
select
*,
current_timestamp() as created_at
from bank_raw;
Edit: To enforce a default, you cannot alter a table to add a column with a default value except for sequences. So you'd need to do something like this:
select get_ddl('table','BLANK_RAW');
-- Copy and paste the DDL. Rename the new table,
-- and add the default timestamp:
create or replace table A
(
-- Existing columns here then:
created_at timestamp default current_timestamp
);
You can then do an insert from a select on the table BLANK_RAW. You'll need to specify a column list and omit the CREATED_AT column.

hive partition by time

I want to implement
alter table dos_sourcedata add partition (data = to_date (current_timestamp ()));
in hive
Run this statement at a specific time every day.
but this is always wrong.
If you want to create empty partition using alter table, use value, not expression, like this:
alter table mytable add partition (partition_date='2020-04-01');
You can create partitions dynamically when loading data using insert overwrite table partition, in this case you can use expression in the query:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
insert overwrite table mytable partition (partition_date)
select
col_1,
...
col_n,
current_date --partition column is the last one
from ...
Use current_date instead of to_date (current_timestamp ()).

Get just Inserted/Modified record based on updated_timestamp

I want to get just Inserted/Modified record based on updated_timestamp.
I have following scenario for DB2 database:
Triggering insert or update query to DB. The table contains updated_timestamp field which capture the insert or updated time.
Want to get my previous inserted/ updated record only using select query.
Example
insert into table_name(x,y,CURRENT TIMESTAMP);
want to get the above inserted record using select as
select * from table_name where updated_timestamp > ?
with what value should I replace the ?, above query should return me latest inserted record as x,y,<time_stamp>
If I understand what your asking, couldn't you use a subquery pulling the max(updated_timestamp) and other values from the table and use that to filter to only the most recently updated records for each one?
Something like this:
insert into table_name (x, y, timestamp)
Select table_name.x, table_name.y, DateTime()
from table_name join (select x, y, Max(updated_timestamp)
updated_timestamp from table_name) table_name2
on table_name.x = table_name2.x and table_name.y = tablename2.y
and table_name.updated_timestamp = table_name2.updated_timestamp
if your db2 version as this option you can use final table like this
SELECT updated_timestamp
FROM FINAL TABLE (INSERT INTO table_name (X, X, updated_timestamp )
VALUES(valueforX, valueforY, CURRENT TIMESTAMP));
look IBM Doc
you can use a variable too:
CREATE OR REPLACE VARIABLE YOURLIB.MYTIMESTAMP TIMESTAMP DEFAULT CURRENT TIMESTAMP;
INSERT INTO table_name (X, X, updated_timestamp )
VALUES(valueforX, valueforY, YOURLIB.MYTIMESTAMP));
but the best solution is update your table with you primary key and get your timestamp with your primary key after.
A suggestion, you use trigger for update last timestamp. May be can you use autotimestamp like this :
CREATE TABLE table_name
(
X VARCHAR(36),
Y VARCHAR(36),
CHANGE_TS TIMESTAMP FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP NOT NULL
)

How to insert multiple default rows into a table in PostgresQL

I have a table with columns taking default values:
create table indexing_table
(
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
);
How do I insert multiple default rows into this table? Do I have to repeat the command:
insert into indexing_table default values;
as many times as I want it to be inserted?
When you have a default value, you can tell the database to use this default value:
INSERT INTO indexing_table(id, created_at)
VALUES(default, default),
(default, default),
(default, default);
If you need hundreds of default records and one of your defaults is "now()", use generate_series():
INSERT INTO indexing_table(created_at)
SELECT NOW() FROM generate_series(1,100);
I have same problem. Have header table which contains only id generated by sequence. I need insert rows into snapshot table and of course i must first fill header. So i have temporary table with many rows and want insert fast to both table.
Loop is easy to write, but its not a way to optimize query (In actualization process it run several thousand times on diferent databases/schemes)
Could run insert with specific values
INSERT INTO csh33 (id)
SELECT (SELECT last_value FROM csh33_id_seq) + row_number() OVER ()
FROM temp_tss11;
-- Primary key "id" is Serial so dont name it
INSERT INTO css33 (header_id, time_from, time_to, code, name)
SELECT (SELECT last_value FROM csh33_id_seq) + row_number() OVER (), now(), null, code, name, FROM temp_tss11;
SELECT setval('csh33_id_seq', (SELECT max(id) FROM csh33) + 1);
Or i could don't name fields with default values
INSERT INTO csh33 SELECT FROM temp_tss11;
-- But must consider raised sequence in filling snapshot table (Don't care about ordering, so only subtract)
INSERT INTO css33 (header_id, time_from, time_to, code, name)
SELECT (SELECT last_value FROM csh33_id_seq) - row_number() OVER (), now(), null, code, name, FROM temp_tss11;
But for you question
INSERT INTO yourTableName SELECT generate_series(1,100)
Note i use PG 9.4
An option if you do not want to name any column keeping the default values syntax is to build it dynamically:
do $$
begin
execute (
select string_agg('insert into indexing_table default values',';')
from generate_series(1,10)
);
end; $$;
do
execute
The simplist way is to insert now() into the "created_at" column like so:
insert into indexing_table (created_at)
select now()
;

mysql automatically store record creation timestamp

Is there some way mysql can store timestamp automatically in a record row whenever that it is created. I was trying to use timestamp(data type) with current_timestamp as default value but then realised this will get updated everytime the record is updated. I just need something that will store create timestamp.
Thanks
Set the DEFAULT constraint to use CURRENT_TIMESTAMP:
CREATE TABLE ...
your_date_column DATETIME DEFAULT CURRENT_TIMESTAMP
...
For an existing table, use the ALTER TABLE statement:
ALTER TABLE your_table
ALTER COLUMN date_column SET DEFAULT CURRENT_TIMESTAMP
Unless you specify a value to for the date_column, the default will be the date & time the INSERT statement was run. NULL and DEFAULT or valid values to use the default constraint otherwise, assuming the column is nullable.
You can get the full details on timestamps in MySQL at https://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html.
The point that you care about is that if you define a timestamp column as DEFAULT CURRENT_TIMESTAMP clause and don't have an ON UPDATE clause, the column has the current timestamp for its default value but is not automatically updated.
But be warned. The obvious thing to want to do is to have two timestamp columns, one being the creation time and the other being the last update time. Unfortunately it is a documented MySQL limitation that MySQL does not support this. I have no idea why MySQL has such an odd limitation - no other major database has problems with this common use case.
FYI = "Datetime" is date and time fixed. "Timestamp" is variable date and time-- system time.
So, Have two columns. One Create Col, One Update Col.
The following command will create a hello table
1. id integer
2. create_at with current time.
create table hello (id int, created_at datetime DEFAULT CURRENT_TIMESTAMP);
Create Table myTableName
(
userId int primary key
userJoiningDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
https://www.mysqltutorial.org/mysql-timestamp.aspx
Here is how you can create a column in which the time stamp is recorded when it is created. If you want to know How to update timeStamp each time that row is changed/updated, Check the above link.
SELECT * FROM test WHERE timestamp >= CURDATE() AND timestamp < CURDATE() + INTERVAL 1 DAY ORDER BY timestamp;