Using CASE Statement in a table - sql

Is it possible to have a column in a table (not from view)(SQL SERVER 2008) to change according to a value in another column i.e. if I have a column called "DUEDATE" can I have a column called "STATUS" that will change the status to "Now Due" if the "DUEDATE" is > GetDate()? If so how do you add that to a table?

You can alter the table and add a computed column:
ALTER TABLE dbo.TheTable
ADD Status AS CASE WHEN ...
You can't persist it, because it's non-deterministic, so don't add PERSISTED or try to put an index on it.
From an indexing perspective, don't try to query it using WHERE Status = 'whatever', because it will have to consider every row in the table. Instead, use an index on DueDate and WHERE DueDate <= GETDATE()

Yes, you can create a computed column:
CREATE TABLE [dbo].[SampleTable](
[DueDate] [date] NULL,
[ComputedValue] AS (CASE WHEN [Duedate] > GETDATE() THEN 'Now Due' ELSE '' END)
) ON [PRIMARY]
As this is a non-deterministic column (because of the value of GETDATE() that is different every time you use the table), adding it to the table doesn't give you much benefit over returning the same in a select query.

Related

change type of a computed column to uncomputed in sql

I have some computed columns in my DB with data. Is there anyway to change type of those columns to uncomputed without dropping and copying their data into new uncomputed columns?
For example I want to change
[Fee] AS CONVERT([decimal](19,4),(case when [Quantity]=(0) then (0) else [Price]/[Quantity] end)) PERSISTED,
to
[Fee] [decimal](26, 16) NOT NULL,
The exact answer is "it depends." MySQL doesn't even have computed columns. In SQL Server, I don't think it is possible. In Oracle it can be done with alter table t1 modify fee DECIMAL( m, n ).
However, even when allowed, the DBMS is probably behind the scenes creating a new column, moving the computed value to the new column, dropping the computed column and renaming new column to computed column name. So even if the conversion is not explicitly allowed, you can still get it done.
Computed Columns do not store data in themselves.
When you try to select the column in a query it computes the data and shows you. Also you can not modify computed columns to uncomputed columns.
But you can do this instead:
Create Table Temp (ID BigInt, value Computed_Column_DataType)
Go
Insert Temp(ID, Value)
Select ID, ComputedColumnName
From Your_Table
Go
Alter Table Your_Table Drop Column ComputedColumnName
Go
Alter Table Your_Table Add ComputedColumnName Computed_Column_DataType
Go
Update Your_Table Set ComputedColumnName = A.Value From Temp A Where A.ID = YourTable.ID

Automatically update a column with a special date in SQL Server

I have a table with 2 columns:
ExpireDate(DateTime)
IsExpired(Bit).
Is there any way that I can check automatically if ExpireDate >= Today Date and change the IsExpired column from false to true?
In fact, I would this process happened for each record in ExpireDate and I don't want check all of record manually to found what recode is expire then change IsExpired column.
You can change the IsExpired field with an update query like this:
UPDATE table SET IsExpired = 1 WHERE ExpireDate >= GetDate()
And if you want it to happen automatically you can schedule a job doing this using the SQL Server Agent.
Try following :
update yourtablename
set isexpired = 1
where ExpireDate >= convert(date,getdate())
If you want this to happen automatically, then use a view or computed column. You can add a computed column like this:
alter table YourTable
add column isexpired as (case when ExpireDate >= getdate() then 1 else 0 end);
(You might have to drop the column first.)
The advantage of a computed column is that it never gets out of date.

How do I create column calculated from another column?

I need to create a column age in a SQL Server database.
The values of this column should be calculated based on the values of the column DOB.
Also its values should increment as Age increases.
You should use a computed column to solve this problem. Something with a definition similar to this:
ALTER TABLE Customers ADD Age AS datediff(year, DOB ,getdate())
Original statement taken from and further information available at BlackWasp.
Edit:
MSDN explains computed columns as:
A computed column is computed from an expression that can use other
columns in the same table. The expression can be a noncomputed column
name, constant, function, and any combination of these connected by
one or more operators. The expression cannot be a subquery.
Unless otherwise specified, computed columns are virtual columns that
are not physically stored in the table. Their values are recalculated
every time they are referenced in a query. The Database Engine uses
the PERSISTED keyword in the CREATE TABLE and ALTER TABLE statements
to physically store computed columns in the table. Their values are
updated when any columns that are part of their calculation change. By
marking a computed column as PERSISTED, you can create an index on a
computed column that is deterministic but not precise. Additionally,
if a computed column references a CLR function, the Database Engine
cannot verify whether the function is truly deterministic. In this
case, the computed column must be PERSISTED so that indexes can be
created on it. For more information, see Creating Indexes on Computed
Columns.
Computed columns can be used in select lists, WHERE clauses, ORDER BY
clauses, or any other locations in which regular expressions can be
used, with the following exceptions:
Computed columns used as CHECK, FOREIGN KEY, or NOT NULL constraints must be marked
PERSISTED. A computed column can be used as a key column in an index or as part of any
PRIMARY KEY or UNIQUE constraint if the computed column value is defined by a
deterministic expression and the data type of the result is allowed in index
columns.
For example, if the table has integer columns a and b, the computed column a + b can be
indexed, but computed column a + DATEPART(dd, GETDATE()) cannot be indexed because the
value may change > in subsequent invocations.
A computed column cannot be the target of an INSERT or UPDATE statement.
The Database Engine automatically determines the nullability of
computed columns based on the expressions used. The result of most
expressions is considered nullable even if only nonnullable columns
are present, because possible underflows or overflows will produce
null results as well. Use the COLUMNPROPERTY function with the
AllowsNull property to investigate the nullability of any computed
column in a table. An expression that is nullable can be turned into a
nonnullable one by specifying ISNULL(check_expression, constant),
where the constant is a nonnull value substituted for any null result.
Source: MSDN - Computed Columns
Code snippet
ALTER TABLE
TheTable
ADD
DOB AS
CASE
WHEN
MONTH(Birth) > MONTH(ISNULL(Death, SYSDATETIME()))
OR (
MONTH(Birth) = MONTH(ISNULL(Death, SYSDATETIME()))
AND DAY(Birth) >= DAY(ISNULL(Death, SYSDATETIME()))
)
THEN
DATEDIFF(YEAR, Birth, ISNULL(Death, SYSDATETIME())) - 1
ELSE
DATEDIFF(YEAR, Birth, ISNULL(Death, SYSDATETIME()))
END
Create Table with auto-generated column,
CREATE TABLE Person2
(Id int IDENTITY(1,1) NOT NULL, Name nvarchar(50),
DOB date, Age AS DATEDIFF(YEAR, DOB ,GETDATE()) )
This is the correct way of getting the age:
alter table <yourtable> add age as datediff(year, DOB, getdate())- case when month(DOB)*32 + day(DOB) > month(getdate()) * 32 + day(getdate()) then 1 else 0 end

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()
)

sql server 2008 function on two date columns

I would like to create a function for a table that has three columns amongst others as follows:
insertDate datetime
updateDate datetime
activity integer
I want to update the activity column by taking the difference of the two date columns...basically updateDate - insertDate = how many days of activity in the activity column. I have no idea how to start this and it needs to run whenever a new insertDate or updateDate is inserted.
You can populate the [InsertDate] with a default value of GETDATE() and populate [UpdateDate] with the current date when you update the column (because you're using procedures (wink), this is really easy to control). If you aren't using procedures and want to control. the [UpdateDate] column, you can use a trigger to populate that column.
Let the Activity column be a calculated field:
DATEDIFF(day, [InsertDate], [UpdateDate])
DATEDIFF
Computed Columns
From MSDNabout computed columns:
Unless otherwise specified, computed columns are virtual columns that are
not physically stored in the table. Their values are recalculated every
time they are referenced in a query. The Database Engine uses the PERSISTED
keyword in the CREATE TABLE and ALTER TABLE statements to physically store
computed columns in the table. Their values are updated when any columns
that are part of their calculation change. By marking a computed column as
PERSISTED, you can create an index on a computed column that is
deterministic but not precise.
Since all the data required for this is in the same row of the table, you could create a computed column. If you want to have an actual column value that is updated whenever the row is updated then you need to look at triggers.
Place this code in a trigger.
update MyTable
set updateDate = GETDATE()
, activity = select (DATEDIFF(DAY, insertDate, GETDATE()))