Disabling INSERT operations on Default Value Columns - SQL Server - sql

In Sql Server 2008, I have a table that is filled by a data provider application.
I want to keep an "INSERT_DATE" column on table, so that I can know the date the record is inserted.
In order to do this, I defined a default constraint on INSERT_DATE column which puts GETDATE() by default.
However, I don't want this column value to be overwritten by data provider application.
So, how can I disable insert into INSERT_DATE column?
(I cannot use computed column. Because Clustered Index uses INSERT_DATE field)

You could use an After Insert trigger. That way, whatever is inserted into that column for an inserted row you could update to the current date/time.

You probably don't want the column updates as well when the row is subsequently updated.
Your best bet is to use a trigger. You might not be able to throw an error if the application provides a value but at least you will be able to set it right by skipping the column in the insert you specify in your trigger.

Related

performance impact of default value set on table's column in postgresql

if a table have default value on a column for e.g.
create table emp
(
flag smallint default 1
)
so is there any impact of this default column in bulk import , if I am not using in insert statement.
According to the docs:
Before 11:
Adding a column with a default requires updating each row of the table (to store the new column value). However, if no default is specified, PostgreSQL is able to avoid the physical update. So if you intend to fill the column with mostly nondefault values, it's best to add the column with no default, insert the correct values using UPDATE, and then add any desired default as described below.
source
11 and after:
From PostgreSQL 11, adding a column with a constant default value no longer means that each row of the table needs to be updated when the ALTER TABLE statement is executed. Instead, the default value will be returned the next time the row is accessed, and applied when the table is rewritten, making the ALTER TABLE very fast even on large tables. However, if the default value is volatile (e.g., clock_timestamp()) each row will need to be updated with the value calculated at the time ALTER TABLE is executed. To avoid a potentially lengthy update operation, particularly if you intend to fill the column with mostly nondefault values anyway, it may be preferable to add the column with no default, insert the correct values using UPDATE, and then add any desired default as described below.
source
If you take a look into the source for the generator/planner/optimizer/rewriter
( postgresql/src/backend/rewrite/rewriteHandler.c around line#1112, function build_column_default() ) :
The default value(or function, e.g. for serials) is fetched from the catalogs and added once to the query tree. So, the DEFAULT may even be more efficient than fetching separate values for all affected rows from one of the tables in query.
But you would have to measure the difference to be sure.

DB2 Automatic Initialization and Updating for TIMESTAMP

I would like to append two timestamp columns to an existing table.
CREATED_TSTMP would be populated with the current timestamp when a record is inserted and LAST_UPD_TSTMP would be updated automatically when a record in the table gets updated.
I would like to do this without having to modify existing queries.
I have the following DDL statements:
ALTER TABLE XXX ADD CREATED_TSTMP TIMESTAMP NOT NULL WITH DEFAULT CURRENT TIMESTAMP ;
alter table XXX add column LAST_UPD_TSTMP timestamp not null generated by default for each row on update as row change timestamp ;
However once the columns are appended, this will cause an existing query with the following syntax:
INSERT INTO XXX VALUES(?,?,?,?,?,?,?,?,?,?)
to fail with
The number of values assigned is not the same as the number of
specified or implied columns or variables..
Is there any way around this problem without having to inspect all of the existing queries (there are hundreds of them...)
If you add the IMPLICITLY HIDDEN option when creating the columns, they will be ignored by the SQL statements unless you explicitly mention these columns.
PS. I'm assuming you are on a sufficiently recent version of DB2, because of your using row change timestamp. To avoid ambiguity, you should indicate the DB2 version and platform in question.

Sql Server - How to get last id inserted into table

I'm trying to get the last id inserted into a table.
I was using
SELECT IDENT_CURRENT('TABLE')
But the problem is that it doesn't return the last inserted id, it returns the max inserted id.
For example, if i do:
INSERT INTO 'TABLA' (ID) VALUES (100)
SELECT IDENT_CURRENT('TABLE') returns 100
but then if i do
INSERT INTO 'TABLA' (ID) VALUES (50)
SELECT IDENT_CURRENT('TABLE') returns 100
and I want to get 50
I need the ID of a specific table, and I generate the id dinamically, so it's not an identity
How can i do it?
From your code, it looks like ID is not an identity (auto-increment) column, so IDENT_CURRENT isn't going to do what you are expecting.
If you want to find the last row inserted, you will need a datetime column that represents the insert time, and then you can do something like:
SELECT TOP 1 [ID] FROM TABLEA ORDER BY [InsertedDate] DESC
Edited: a few additional notes:
Your InsertedDate column should have a default set to GetDate() unless your application, stored procs or whatever you use to perform inserts will be responsible for setting the value
The reason I said your ID is not an identity/auto-increment is because you are inserting a value into it. This is only possible if you turn identity insert off.
SQL Server does not keep track of the last value inserted into an IDENTITY column, particularly when you use SET IDENTITY_INSERT ON;. But if you are manually specifying the value you are inserting, you don't need SQL Server to tell you what it is. You already know what it is, because you just specified it explicitly in the INSERT statement.
If you can't get your code to keep track of the value it just inserted, and can't change the table to have a DateInserted column with a default of CURRENT_TIMESTAMP (which would allow you to see which row was inserted last), perhaps you could add a trigger to the table that logs all inserts.
SELECT SCOPE_IDENTITY()
will return the last value inserted in current session.
Edit
Then what you are doing is the best way to go just make sure that the ID Column is an IDENTITY Column, IDENT_CURRENT('Table_name'), ##IDENTITY and SCOPE_IDENTITY() returns last value generated by the Identity column.
If the ID column is not an Identity Column, all of these functions will return NULL.

How do I set a value for existing rows when creating a new timestamp column?

I have the following table:
Study id
Pepsi 1
Coke 2
Sprite 3
I need to add a new column timestamp in the above table. i.e, study creation time and date will be stored in this column. What value should I have set for existing rows? Or should the "Timestamp" column have a value only for newly created rows?
I have used the following query to add the new column:
alter table Study add Timestamp datetime
There is no way to tell you what value you should set for existing rows - that is up to you to decide. If you can somehow retrieve the creation time by piecing together other information, then perhaps you can do this one by one, or you could just leave the existing rows to NULL.
Setting a default like GETDATE() for the column, and setting it to NOT NULL, forces all of the existing rows to inherit the current date and time - and you won't be able to set those back to NULL. I'm quite opposed to using garbage token values like 1900-01-01 to represent unknown, and I also don't believe in modifying the code to say something like "if the date is October 8, 2013 then that's because we just didn't know." So I would suggest adding a NULLable column with a default:
ALTER TABLE dbo.Study ADD CreationTime DATETIME NULL DEFAULT CURRENT_TIMESTAMP;
GO
Note that if you leave the column nullable, then the DEFAULT constraint is only useful if DML never sets it to NULL. If an INSERT statement, for example, explicitly places NULL there, the default is ignored. A way around this is to use a trigger (just like you would handle an update):
CREATE TRIGGER dbo.StudyCreationTime
ON dbo.Study
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE s
SET s.CreationTime = CURRENT_TIMESTAMP
FROM dbo.Study AS s
INNER JOIN inserted AS i
ON s.StudyID = i.StudyID;
END
GO
what value should i have to set for previous studies
This would have to be defined by your business. This doesn't require a technical answer, so no one here can tell you what is right.
I have used below query to adding new column:
alter table Study add Timestamp datetime
This will work just fine, though this will allow nulls. I might suggest making this column non-null, adding a default, and changing the name of the column slightly since timestamp is a reserved word in SQL Server (a datatype that has not much to do with dates or times):
alter table Study add CreateDate datetime not null default current_timestamp;
Note that this will set all rows to the current date and time, so you may want to update them if you have more accurate data. Alternatively, simply create the column as nullable and existing rows won't get the default value, but rather null instead.
Another choice you might have to make is whether to use local time or UTC time (e.g. default getutcdate()). You might want to use the same time that your servers use or that other "CreateDate" columns use.

Can you tell me when data was inserted into a table

I am using MS SQL Server 2008 and I have an sql table with some data that is inserted daily at 6 am by an sql job. The problem I have is that some data has been inserted separately into the job and I need to know when this data was added.
Is there a query I can run that will show me this?
I think the short answer is NO, there's no magic, ad hoc SQL query that will let you go back after the fact and find out when a row was inserted.
If you want to know when a row is inserted, the easiest thing would be to simply add a date or timestamp field with a default value (like getDate()) that automatically fills in the date/time when the row is inserted.
There are, of course, SQL logs available that will let you track when rows are inserted, updated, deleted, etc., but those require set up and maintenance.
Third option would be to have the program that's inserting the data perform some logging.
Add a date field to the table. You can give it a default value of GETDATE()
Then ORDER BY that field.
SELECT Column1, Column2, NewDateColumn
FROM YourTable
ORDER BY NewDateColumn
what i would do is :
/* add new column to keep inserted row date */
ALTER TABLE [schemaName].[tableName] ADD [RecTime] DATETIME;
/* update the existing rows with the current date since there is no way to guess their insertion date */
UPDATE [schemaName].[tableName] SET [RecTime] = GETDATE();
/* and set a constraint to the RecTime column to set current date on every new row added */
ALTER TABLE [schemaName].[tableName] ADD CONSTRAINT [DF_tableName_RecTime] DEFAULT (GETDATE()) FOR [RecTime]
then you can get those rows like :
SELECT *
FROM [schemaName].[tableName]
WHERE NOT(DATEPART(hh, RecTime) = 6 AND DATEPART(mi, RecTime) <= 20)
you can 'play' with '20' if you know how long sql job run
you probably need to look at SQL CREATE TRIGGER to add the logic to know when the data is being added and log that info in another table for further actions. Without further details I am not sure we can say more than that.
As you're referring to data which has already been inserted, the answer is No, unless you already have a datetime column which has a default value of GETDATE(). The best you can manage after the event has occurred is to look at the sequence of rows and determine that it was between two known times.