SQL - Multiple fields are updated instead of one - sql

I have four columns: ID, STARTTIME, ENDINGTIME and DURATION.
The table is created with:
CREATE TABLE tableName (
ID INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
STARTTIME TIMESTAMP,
ENDINGTIME TIMESTAMP,
DURATION TIME);
The ID is an auto_increment column. Then I've the code for inserting a new STARTTIME:
INSERT INTO tableName(STARTTIME) VALUES(CURRENT_TIMESTAMP);
Secondly I've the code for updating the row with the biggest ID to set the ENDINGTIME:
SET #latestInsertID = (SELECT MAX(ID) FROM tableName);
UPDATE tableName SET ENDINGTIME=(CURRENT_TIMESTAMP) WHERE ID=#latestInsertID;
Now I can execute both (all three) queries without getting an exception and the first query works totally fine (as I expected). But the last query updates (from the row I wanted to update) the ENDINGTIME as well as the STARTTIME. Why doesn't it just update the ENDINGTIME?
Thank you for every solution!

Use DATETIME instead of TIMESTAMP (MWE)
Here's why:
The timestamp field is generally used to define at which moment in time a row was added or updated and by default will automatically be assigned the current datetime when a record is inserted or updated. The automatic properties only apply to the first TIMESTAMP in the record; subsequent TIMESTAMP columns will not be changed.

Educated guess. Column is defined as:
CREATE TABLE tablename(
-- ...
STARTTIME TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Or there is underlying trigger that perfroms same logic.

Related

Add a column with the current timestamp to a table in Hive

I'm trying to add a column called tstamp to a table that I've created. The column is to have the current timestamp in the format 'yyyy-MM-dd' populating each row.
I initially created the table from another table (table1) using the statement:
create location2.table2
as (select *
from location1.table1
);
I then used the alter table statement to add a field called tstamp to table2 using the code:
alter table location2.table2
add columns (tstamp date)
and I can see that this has successfully added a column to table2 named tstamp and populated each row of this table as null. I am now trying to insert the current date into every row in the field tstamp but am struggling to do so. I've tried using the insert into statement as:
insert into location2.table2 (tstamp)
values (to_date(current_timestamp()))
but get the error "Expression of type TOK_FUNCTION not supported in insert/values". I then also tried to add just a string and replaced the function with '2019-07-25'. Doing this added a new row to my table with null values in every column except tstamp which had a value '2019-07-25'. I'm now confused as it appears my approach was not the right one for the problem and am unsure where to go from here. Any help would be greatly appreciated.
create location2.table2 as (select current_date as tstamp,* from location1.table1 );

sql when set default value getdate(), does it set value when run update statement?

I know when you insert a value into db, it set that column value as current datetime,
does it apply to it when you run a update statement?
e.g.
table schema:
Id, Name, CreatedDate(getdate())
when i insert into table id = 1 , name = 'john' it will set createdDate = current date
if i run an update statement
update table set name="john2" where id =1
Will it update the createdDate?
No, a DEFAULT CONSTRAINT is only invoked on INSERT, and only when (a) combined with a NOT NULL constraint or (b) using DEFAULT VALUES. For an UPDATE, SQL Server is not going to look at your DEFAULT CONSTRAINT at all. Currently you need a trigger ( see How do I add a "last updated" column in a SQL Server 2008 R2 table? ), but there have been multiple requests for this functionality to be built in.
I've blogged about a way to trick SQL Server into doing this using temporal tables:
Maintaining LastModified Without Triggers
But this is full of caveats and limitations and was really only making light of multiple other similar posts:
A System-Maintained LastModifiedDate Column
Tracking Row Changes With Temporal
Columns
How to add “created” and “updated” timestamps without triggers
Need a datetime column that automatically updates
wow - hard to understand...
i think NO based on the clues.
if you insert a record with a NULL in a column, and that column has a default value defined, then the default value will be stored instead of null.
update will only update the columns specified in the statement.
UNLESS you have a trigger that does the special logic - in which case, you need to look at the trigger code to know the answer.
if your update statement tell to update a column with getfate() it will, but if you just update a name for example and you have a createdate column (which was inserted with getdate()), this columns wont be affected.
You can achieve this using DEFAULT constraint like i did it with OrderDate field in below statement.
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
OrderDate date DEFAULT GETDATE()
)

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;

Informix 7.3 - Declaring a date column data type with default as current date on insert/update

Looking for your help again Jonathan Leffler!
I am creating a table on Informix 7.3 and need a timestamp field that will default to today on inserts and updates.
How can I define a date/datetime/timestamp column for a table with a default value of the current time?
Here is a field definition for a simple date field:
column upd_date date
comments ""
desc "Last update date"
heading "Last update date"
text "Last update date"
attributes
(
)
There is also some other syntax in schema files that have comments about what the default should be:
column beg_date date{DEF: date academic session/subsession officially begins}
comments ""
desc "Beginning date."
heading "Beg Date"
text "Date - Begin"
attributes
(
)
I'm not sure of any other tables that have this functionality, and I'm not even 100% sure that it is supported, but if there is a way, I'd love to know.
The only good lead I've found on the topic is here
Anyone have any ideas/solutions?
More findings:
http://www.4js.com/techdocs/genero/fgl/devel/DocRoot/User/DatabaseSchema.html
Cast Date in Informix
There is a datetime column type that I found in another table def:
column beg_time datetime year to minute
comments ""
desc "Beginning date and time of period"
heading "Beg Time"
text "Date/Time - Slot Begin"
attributes
(
)
{DEF: date and time this group/person may register}
I don't recognize the meta-language used in the question, so I'm not sure what that is capable of compared with what the DBMS is capable of.
CREATE TABLE ExampleDatesAndTimes
(
rownumber SERIAL NOT NULL PRIMARY KEY,
date_column DATE DEFAULT TODAY NOT NULL,
datetime_yd DATETIME YEAR TO DAY
DEFAULT CURRENT YEAR TO DAY NOT NULL,
datetime_ys DATETIME YEAR TO SECOND
DEFAULT CURRENT YEAR TO SECOND NOT NULL,
datetime_hs DATETIME HOUR TO SECOND
DEFAULT CURRENT HOUR TO SECOND NOT NULL,
payload VARCHAR(255) NOT NULL
);
This gives you a table in which each of the 4 temporal columns will be assigned a default value if you don't specify it in the INSERT operation:
INSERT INTO ExampleDatesAndTimes(Payload) VALUES ("Hello");
On the other hand, if you specify the columns, then the specified values take precedence. I'm assuming the DBDATE="Y4MD-" so that DATE values look like DATETIME YEAR TO DAY values:
INSERT INTO ExampleDatesAndTimes
VALUES(0, '1066-10-14', '2001-01-01', '2012-11-10 09:08:07',
'23:23:21', "Gezundheit");
Here, the values are all specified, so those are the values stored. Note that programs such as ISQL Perform (and most typical I4GL programs) will provide values for all the columns so the default mechanism won't take effect.
You can play with triggers to alter the values on UPDATE, so you can have a date inserted and a 'last updated' column (and whodunnit columns - created_by and updated_by - if you want). Again, you have to worry about defaults versus explicitly provided values.
Now, since you are using IDS 7.3x, which finally went out of service a year or two ago, you have slightly different functionality from what is available in IDS 11.70. You should be looking at upgrading.
I found this code (eventually) for playing with triggers on update. It dates from 2006.
CREATE TABLE talx_000
(
i SERIAL NOT NULL PRIMARY KEY,
s CHAR(30) NOT NULL,
m_user VARCHAR(32) DEFAULT USER NOT NULL,
m_time DATETIME YEAR TO SECOND DEFAULT CURRENT YEAR TO SECOND NOT NULL
);
CREATE PROCEDURE current_user_time()
RETURNING VARCHAR(32) AS m_user, DATETIME YEAR TO SECOND AS m_time;
RETURN user(), CURRENT YEAR TO SECOND - 1 UNITS DAY;
END PROCEDURE;
CREATE TRIGGER upd_talx_000 UPDATE ON talx_000
REFERENCING NEW AS NEW FOR EACH ROW
(EXECUTE PROCEDURE current_user_time() INTO m_user, m_time);
INSERT INTO talx_000(s) VALUES("cached nonsense");
INSERT INTO talx_000(s, m_user) VALUES("inserted user", "sphinx");
INSERT INTO talx_000(s, m_time)
VALUES("inserted time", DATETIME(1066-10-14 15:23:31) YEAR TO SECOND);
INSERT INTO talx_000(s, m_time, m_user)
VALUES("inserted both", DATETIME(1805-10-21 13:15:00) YEAR TO SECOND,
"nelson");
SELECT * FROM talx_000;
DROP TRIGGER upd_talx_000;
CREATE PROCEDURE upd_talx_000(i_val INTEGER);
UPDATE talx_000
SET m_user = "brandywine",
m_time = DATETIME(3019-03-25 13:00:00) YEAR TO SECOND
WHERE i = i_val;
END PROCEDURE;
CREATE TRIGGER upd_talx_000 UPDATE ON talx_000
REFERENCING NEW AS NEW FOR EACH ROW
(EXECUTE PROCEDURE upd_talx_000(NEW.i));
INSERT INTO talx_000(s) VALUES("cached nonsense");
INSERT INTO talx_000(s, m_user) VALUES("inserted user", "sphinx");
INSERT INTO talx_000(s, m_time)
VALUES("inserted time", DATETIME(1066-10-14 15:23:31) YEAR TO SECOND);
INSERT INTO talx_000(s, m_time, m_user)
VALUES("inserted both", DATETIME(1805-10-21 13:15:00) YEAR TO SECOND,
"nelson");
SELECT * FROM talx_000;
Have fun!
TABLE sample
(
timestamp DATETIME(YEAR TO SECONDS)
)
In Informix-SQL Perform screen:
INSTRUCTIONS
AFTER EDITADD OF sample.timestamp
LET screen_tag = CURRENT
AFTER EDITUPDATE OF sample.timestamp
LET screen_tag = CURRENT
NOTE: I never use WITHOUT NULL on a DATE or DATETIME column since it's better to have an absent value as opposed to 12/31/1899 when WITHOUT NULL is specified on a temporal column.
This is tested & works for me - ONLY FOR INSERTS. I assume that you can handle the update scenario with a trigger if you need the field to update to the current date on every update
column use_date date default today not null
comments ""
desc "Date this use case was executed"
heading "Usage date"
text "Usage date"
attributes
(
)

Change each record in a table with no primary key?

I have a table in a database that represents dates textually (i.e. "2008-11-09") and I would like to replace them with the UNIX timestamp. However, I don't think that MySQL is capable of doing the conversion on its own, so I'd like to write a little script to do the conversion. The way I can think to do it involves getting all the records in the table, iterating through them, and updating the database records. However, with no primary key, I can't easily get the exact record I need to update.
Is there a way to get MySQL to assign temporary IDs to records during a SELECT so that I refer back to them when doing UPDATEs?
Does this not do it?
UPDATE
MyTable
SET
MyTimeStamp = UNIX_TIMESTAMP(MyDateTime);
If for some reason you do have to iterate (the other answers cover the situation where you don't), I can think of two ways to do it (these aren't MySQL-specific):
Add a column to the table that's an auto-assigned number. Use that as the PK for your updates, then drop the column afterwards (or just keep it around for future use).
In a table with no defined PK, as long as there are no exact duplicate rows, you can use the entire row as a composite PK; just use every column in the row as your distinguishing characteristic. i.e., if the table has 3 columns, "name", "address", and "updated", do the following:
UPDATE mytable SET updated = [timestamp value] WHERE name = [name] AND address = [address] AND timestamp = [old timestamp]
Many data access frameworks use this exact strategy to implement optimistic concurrency.
No, you should be able to do this with a single update statement. If all of the dates are yyyy-mm-dd and they are just stored in some sort of text column instead of DATETIME, you can just move the data over. SQL would be like:
ALTER TABLE t ADD COLUMN dates DATETIME;
UPDATE t set t.dates=t.olddate;
This shouldn't be dependent on a PK because MySQL can scan through each row in the table. The only time PK's become an issue is if you need to update a single row, but the row may not be unique.
You can generate values during a SELECT using the MySQL user variables feature, but these values do not refer to the row; they're temporary parts of the result set only. You can't use them in UPDATE statements.
SET #v := 0;
SELECT #v:=#v+1, * FROM mytable;
Here's how I'd solve the problem. You're going to have to create another column for your UNIX timestamps anyway, so you can add it first. Then convert the values in the old datetime column to the UNIX timestamp and place it in the new column. Then drop the old textual datetime column.
ALTER TABLE mytable ADD COLUMN unix_timestamp INT UNSIGNED NOT NULL DEFAULT 0;
UPDATE mytable
SET unix_timestamp = UNIX_TIMESTAMP( STR_TO_DATE( text_timestamp, '%Y-%m-%d' ) );
ALTER TABLE mytable DROP COLUMN text_timestamp;
Of course you should confirm that the conversion has been done correctly before you drop the old column!
See UNIX_TIMESTAMP() and STR_TO_DATE()