I am using MS SQL Server 2008 R2 and I need to have a cell in each row with the date and time of when the row was inserted in the database. Now as I want to script and then load the database in MS SQL Server 2005 I Cannot use datetime or date so I tried to use getdate() function in the Computed Column Specification property. Can anyone please help me.
Thanks
Jean Claude, here is a complete example.
Code
USE tempdb;
SET NOCOUNT ON;
GO
CREATE TABLE dbo.TestTable (
RecordId int IDENTITY,
RecordValue varchar(32) NOT NULL,
RecordCreateDate datetime NOT NULL,
CONSTRAINT PK_TestTable
PRIMARY KEY CLUSTERED (
RecordId
)
)
GO
ALTER TABLE dbo.TestTable
ADD CONSTRAINT DF_TestTable_RecordCreateDate
DEFAULT GETDATE()
FOR RecordCreateDate;
GO
INSERT INTO dbo.TestTable (RecordValue) VALUES ('this');
WAITFOR DELAY '00:00:01';
INSERT INTO dbo.TestTable (RecordValue) VALUES ('that');
WAITFOR DELAY '00:00:01';
INSERT INTO dbo.TestTable (RecordValue) VALUES ('the other thing');
SELECT * FROM dbo.TestTable;
Results
RecordId RecordValue RecordCreateDate
-------- --------------- -----------------------
1 this 2012-05-16 10:43:48.400
2 that 2012-05-16 10:43:49.403
3 the other thing 2012-05-16 10:43:50.403
You should also research the new datetime data types and the SYSDATETIME() function.
Jean Claude, you seem to be under a misapprehension about datetime, which has been supported in every version of SQL Server I've ever used, all the way back to 6.5. It's the Date and Time types that are new in SQL 2008.
Rob's excellent answer should work fine in both SQL 2005 and 2008.
Related
I'm attempting to create a 'history' table that gets updated every time a row on the source table is updated.
Here's the (SQL Server) code I'm using to create the history table:
DROP TABLE eventGroup_History
SELECT
CAST(NULL AS UNIQUEIDENTIFIER) AS NewId,
CAST(NULL AS varchar(255)) AS DoneBy,
CAST(NULL AS varchar(255)) AS Operation,
CAST(NULL AS datetime) AS DoneAt,
*
INTO
eventGroup_History
FROM
eventGroup
WHERE
1 = 0
GO
ALTER TABLE eventGroup_History
ALTER COLUMN NewId UNIQUEIDENTIFIER NOT NULL
go
ALTER TABLE eventGroup_History
ADD PRIMARY KEY (NewId)
GO
ALTER TABLE eventGroup_History
ADD CONSTRAINT DF_eventGroup_History_NewId DEFAULT NewSequentialId() FOR NewId
GO
The trigger is created like this:
drop trigger eventGroup_LogUpdate
go
create trigger eventGroup_LogUpdate
on dbo.eventGroup
for update
as
declare #Now as DateTime = GetDate()
set nocount on
insert into eventGroup_History
select #Now, SUser_SName(), 'update-deleted', *
from deleted
insert into eventGroup_History
select SUser_SName(), 'update-inserted', #Now, *
from inserted
go
exec sp_settriggerorder #triggername = 'eventGroup_LogUpdate', #order = 'last', #stmttype = 'update'
But when I update a row in SQL Server Management Studio, I get a message:
The data in row 2 was not committed.
Error Source: .Net SqlClient Data Provider.
Error Message: Conversion failed when converting from a character string to uniqueidentifier.
I think that the trigger is attempting to insert the SUserSName() as the first column of the row but that is the PK NewId:
There are no other uniqueidentifier columns in the table.
If I add row from the SQL Management Studio's edit grid, the row gets added without me having to specify the NewId value.
So, why is the SQL Server trigger attempting to populate NewId with first item in the INSERT INTO clause rather than skipping it to let the normal IDENTITY operation provide a value?
(And how do I stop this happening so that the trigger works?)
Because the automatic skipping only applies to IDENTITY columns - a GUID column set with the NewSequentialId() constraint behaves similarly to IDENTITY in many ways but not this one.
You can achieve what you are looking for by specifying the columns for the INSERT explicitly.
If you're going to use a default value on your NewId column, you need to explicitly list the column names in the INSERT statements. By default, SQL Server will insert the columns in the order they're listed in the SELECT, unless you give it enough information to do otherwise. Listing out the columns explicitly is a best practice, one way or the other, in order to avoid just this sort of unanticipated result.
So your statements will end up looking like this:
INSERT INTO eventGroup_History
(
DoneBy,
Operation,
DoneAt,
<All the other columns that are masked by the *>
)
SELECT....
I am using Microsoft SQL Server 2014 - 12.0.4100.1 (X64)
I have a string column that is populated with a date.
The problem is that some of the dates come in the format: Oct 17 2017 9:21AM. I need to enforce this format on the column: 2018-01-15 11:22:11.999
I did some research and I know I can set constraints with CHECK () at table creation or I know I can use ISDATE('2014-05-01') but I don't have an end to end solution.
I can clean the current data so this constraint is just for future inserts.
I am looking for a simple solution.
Any ideea? Any suggestion would be much appreciated
EDIT :
Is a legacy solution. I know is a bad approach but I can not change the format of the field! Only relevant solutions to the problem please.
If you have to stick with this you might add a computed column like here:
CREATE TABLE test(SomeSillyDate VARCHAR(100));
INSERT INTO test VALUES ('2018-01-15 11:22:11.99')
,('Oct 17 2017 9:2')
,('invalid date');
GO
ALTER TABLE test ADD CheckedDate AS TRY_CAST(SomeSillyDate AS DATETIME);
GO
SELECT * FROM test;
GO
DROP TABLE test;
But - if there's any chance - you should store this as DATETIME typed value.
You might use a VIEW with the tables name on top of a new table. This would not change the approach from outside...
UPDATE: Trigger approach
CREATE TABLE test(ID INT IDENTITY, SomeSillyDate VARCHAR(100));
GO
CREATE TRIGGER TestTrigger ON test
AFTER INSERT,UPDATE
AS
BEGIN
SET NOCOUNT ON;
WITH UpdCTE AS
(
SELECT t.SomeSillyDate AS oldValue
,ISNULL(FORMAT(TRY_CAST(i.SomeSillyDate AS DATETIME),'yyyy-MM-dd HH:mm:ss'),t.SomeSillyDate) AS newValue
FROM test AS t
INNER JOIN inserted AS i ON t.ID=i.ID
)
UPDATE UpdCTE
SET oldValue=newValue;
END
GO
INSERT INTO test VALUES ('2018-01-15 11:22:11.99')
,('Oct 17 2017 9:2')
,('invalid date');
GO
UPDATE test SET SomeSillyDate = GETDATE() WHERE ID=2;
GO
SELECT * FROM test;
GO
DROP TABLE test;
I am fairly new to SQL Server and I am struggling with creating a trigger that does what I need.
We have a table that before a record is inserted we want to manipulate the input value.
Example table:
MyTable
(
[RUID] INT IDENTITY(1,1),
[CustomerName] nvarchar(200),
[CustomerStatus] INT,
[CustomerType] char(1),
[OtherFields] nvarchar(100)
)
An insert may come in like:
INSERT INTO MyTable ([CustomerName], [CustomerStatus], [CustomerType], [OtherFields])
VALUES ('LName~FName', 2, 'A', 'Other Info')
We don't have control of the source system doing the insert (a vendor product that is on its way out in a couple years so management doesn't want to spend the sums of money to have them alter it) but we need something like this to happen.
CustomerStatus that is inserted to be 2x inserted value
CustomerType - Regardless of the value sent we want to be overridden with a value of 'B'
All other columns are left as is.
So with an insert sent with the values in the example above, we would actually want this to end up in the table:
'LName~FName', 4, 'B', 'Other Info'
Any help you could provide would be greatly appreciated.
Specs:
SQL Server 2008 R2 Standard Edition (Database is in SQL Server 2000 compatibility mode though)
You basically need an Instead of trigger. The code would look something like...
CREATE TRIGGER tr_Insert_MyTable
ON MyTable
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO MyTable ([CustomerName], [CustomerStatus], [CustomerType], [OtherFields])
SELECT [CustomerName]
, [CustomerStatus] * 2 AS [CustomerStatus]
,'B' [CustomerType]
, [OtherFields]
FROM inserted
END
We have a large Database (Many Table, SP, Function and...) and our database programers are over 10 person. All of theme can use the database on our main server computer or on his local system.
Our requirements:
we want each db programmer can apply his definitions (create table, triger, sp, fn &...) and modifications (on tables, sp, trigers, fn &...) by SQL SERVER MANAGMENT STUDIO (or your suggest tool) and get all of this activities as a TSQL Script at the end of each day.
So, we want a automatic log of our db programers activities as a TSQL script (sequence of sub tsql queries). for example:
My Activities:
My first activity>> I open my Customer table as design mode, by right
click on table and click Design. then i change datatype of ID field
from INT to BigInt. then save
My second activity>> I change
PR_Customer_Insert stored procedure and i execute it.
Now i want an executable log like this:
-- UserName: Ram
-- 2013-02-10 10:20:35
Alter Table ALTER TABLE Customer ALTER COLUMN Id TYPE bigint;
Go
-- UserName: Ram
-- 2013-02-10 10:45:00
Drop Sp DROP PROCEDURE dbo.PR_Customer_Insert;
-- UserName: Ram
-- 2013-02-10 10:45:00
Create sp CREATE PROCEDURE PR_Customer_Insert
#id int,
#name nvarchar(30) AS
INSERT INTO Customer
(
#id,
#name
)
GO
We know compare tow database is a solution but we want access to SSMS Query Pipeline...
My Questions:
Is there any way for this request (an automatically generated log that is an executable TSQL script)?
What is the best solutions for generate this scripts automatically???
What do you think about this idea in a team work on database?
Thanks...
Possible use DDL triggers, but on a certain database
Simple example:
--Create table EvtLog
CREATE TABLE EvtLog
(
LoginName NVARCHAR(100),
PostTime DATETIME,
EventType NVARCHAR(100),
TSQLCommand NVARCHAR(2000)
)
GO
--Create the DDL trigger
CREATE TRIGGER trPreventTblChange
ON DATABASE
FOR DROP_TABLE, CREATE_TABLE, ALTER_TABLE,
DROP_PROCEDURE, CREATE_PROCEDURE, ALTER_PROCEDURE
AS
DECLARE #Data XML
SET #Data = EventData()
INSERT EvtLog (LoginName, PostTime, EventType, TSQLCommand)
SELECT #Data.value('(/EVENT_INSTANCE/LoginName)[1]', 'nvarchar(100)'),
#Data.value('(/EVENT_INSTANCE/PostTime)[1]', 'nvarchar(100)'),
#Data.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)'),
#Data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(2000)');
GO
Set up a database DDL trigger and use the EVENTDATA Function to find out more information about what was done and insert that into a table that you can query at the end of the day
Example
CREATE TRIGGER [LogDDL] ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS
AS
DECLARE #xml XML;
SELECT #xml = EVENTDATA();
INSERT ChangeLog
(
ObjectName,
SQL
)
VALUES
(
#xml.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname'),
#xml.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)')
);
The OUTPUT clause is compatible with SQL Server 2005 but not SQL Server 2000.
How do I convert this command to work in SQL Server 2000?
CREATE TABLE sample
(
ID uniqueidentifier NOT NULL DEFAULT newid(),
Title varchar(30) NOT NULL
)
INSERT INTO sample (Title)
OUTPUT INSERTED.ID
VALUES ('Test1')
I need the command to retrieve the ID since the INSERT command needs to be called from a stored procedure.
Thanks for any help!
DECLARE #uid uniqueidentifier
SET #uid = newid()
INSERT INTO sample (ID, Title)
VALUES (#uid,'Test1')
SELECT #uid AS ID