Schema Changes history using t-sql - sql

Is there any DMV or query to track the ddl changes to objects on sql server 2008r2 that incudes the LOGINNAME and SERVERNAME of the USER who altered the specific object
I'm trying to create a monitoring tool that includes this feature.
Please help!
Thank you very much!

You can create DDL trigger for your database like:
CREATE TABLE [dbo].[ddl_log](
[data] [XML] NULL,
[systemuser] [NVARCHAR](255) NULL,
[hostname] [NVARCHAR](255) NULL,
[date] [DATETIME] NULL,
[EventType] [NVARCHAR](255) NULL,
[SPID] [SMALLINT] NULL,
[SchemaName] [NVARCHAR](255) NULL,
[ObjectName] [NVARCHAR](255) NULL,
[ObjectType] [NVARCHAR](255) NULL,
[CommandText] [NVARCHAR](MAX) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TRIGGER [ddl_log_all]
ON DATABASE FOR DDL_DATABASE_LEVEL_EVENTS
AS
SET NOCOUNT ON
INSERT INTO ddl_log (data, systemuser, hostname, date, EventType, SPID, SchemaName, ObjectName, ObjectType, CommandText)
SELECT
EVENTDATA(), SYSTEM_USER, HOST_NAME(), GETDATE(),
EVENTDATA().value('(/EVENT_INSTANCE/EventType)[1]','nvarchar(max)'),
EVENTDATA().value('(/EVENT_INSTANCE/SPID)[1]','smallint'),
EVENTDATA().value('(/EVENT_INSTANCE/SchemaName)[1]','nvarchar(max)'),
EVENTDATA().value('(/EVENT_INSTANCE/ObjectName)[1]','nvarchar(max)'),
EVENTDATA().value('(/EVENT_INSTANCE/ObjectType)[1]','nvarchar(max)'),
EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
GO
ENABLE TRIGGER [ddl_log_all] ON DATABASE
GO
Then any change will be logged in table ddl_log.

Related

How to track deleted rows from database system versioned table in Azure SQL/SQL Server?

I have system versioned Customer table and need to track if admin user deleted the row ('Tesla') from the table.
CustomerHistory table do get new row for 'Tesla', but it does not explicitly tell if row has been updated or deleted.
I would need advice to create SELECT/INSERT SQL query, which compared Customers and CustomerHistory to check which row has been deleted and insert the row ('Tesla') to CustomersDeleted table.
I have System versioned table:
CREATE TABLE [sales].[Customers](
[Customer_PK] [int] IDENTITY(1,1) NOT NULL,
[Customer_Id] [smallint] NULL,
[Customer_Name] [nvarchar](150) NULL,
) ON [PRIMARY]
GO
It has value '1','100','Tesla' and '2','200','Ford'.
Admin user will deleted 'Tesla' row.
I have History versioned table:
CREATE TABLE [sales].[CustomersHistory](
[Customer_PK] [int] NOT NULL,
[Customer_Id] [smallint] NULL,
[Customer_Name] [nvarchar](150) NULL,
) ON [PRIMARY]
GO
I have third table where I would like to insert rows ('Tesla') that has been removed from Customer table.
CREATE TABLE [sales].[CustomersDeleted](
[Customer_PK] [int] NOT NULL,
[Customer_Id] [smallint] NULL,
[Customer_Name] [nvarchar](150) NULL,
[Deleted_time] [datetime2](7) NULL
) ON [PRIMARY]
GO

SQL AZURE : An error occurred while executing GlobalQuery operation: Large object column support is limited to only nvarchar(max) data type

Sql azure query: after creating external table i run select query to get data from external table but this error occures!
i removed all columns with datatype = nvarchar(max) but also the problem have not been solved yet!
Code to create external table:
CREATE External TABLE [dbo].[tbl_threads_controlPanel_v](
[thread_id] [varchar](6) NOT NULL,
[thread_desc_criteria] [varchar](300) NOT NULL,
[thread_desc_formula] [varchar](300) NOT NULL,
[thread_type] [char](1) NOT NULL,
[detectType] [char](1) NOT NULL,
[detailed_qry] [nvarchar](300) NULL,
[bottomup_qry] [nvarchar](300) NULL,
[period_desc] [char](1) NULL,
[period_value] [int] NULL,
[period_value_range] [varchar](50) NULL,
--[cond_attribute] [nvarchar](max) NULL,
[cond_min_max_limit] [varchar](30) NULL,
[cond_desc] [varchar](60) NULL,
[active] [char](1) NULL,
[mature] [char](1) NULL,
[pkg_run] [char](1) NULL,
[thread_index] [int] NULL,
[thread_weight] [numeric](12, 11) NULL,
[thread_noti_type] [char](1) NULL,
[notif_id] [varchar](9) NULL,
[amt_type] [nchar](5) NULL--,
--[report_Columns] [nvarchar](max) NULL,
--[OS_Columns] [nvarchar](max) NULL
)
with(DATA_SOURCE = MyElasticDBQueryDataSrc3)
And this is the select query:
select * from dbo.[tbl_threads_controlPanel_v]
Please help ..
Thanks in advance.
UPDATE 2:
This is original tbl_threads definition
USE [DB_IFDPS_ControlPanel]
GO
/****** Object: Table [dbo].[tbl_threads] Script Date: 10/26/2016 8:51:09 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tbl_threads](
[thread_id] [varchar](6) NOT NULL,
[thread_desc_criteria] [varchar](300) NOT NULL,
[thread_desc_formula] [varchar](300) NOT NULL,
[thread_type] [char](1) NOT NULL,
[detectType] [char](1) NOT NULL,
[detailed_qry] [text] NULL,
[bottomup_qry] [text] NULL,
[period_desc] [char](1) NULL,
[period_value] [int] NULL,
[period_value_range] [varchar](50) NULL,
[cond_attribute] [nvarchar](max) NULL,
[cond_min_max_limit] [varchar](30) NULL,
[cond_desc] [varchar](60) NULL,
[active] [char](1) NULL,
[mature] [char](1) NULL,
[pkg_run] [char](1) NULL,
[thread_index] [int] NULL,
[thread_weight] [numeric](12, 11) NULL,
[thread_noti_type] [char](1) NULL,
[notif_id] [varchar](9) NULL,
[amt_type] [nchar](5) NULL,
[report_Columns] [nvarchar](max) NULL,
[OS_Columns] [nvarchar](max) NULL,
CONSTRAINT [PK_tbl_threads] PRIMARY KEY CLUSTERED
(
[thread_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
It looks like this is not the whole story.
The problem seems to be not with the varchar(max) columns but with a column that is defined somewhere else as a LOB but in the external table is defined otherwise than varchar(max)
Thanks for adding the relevant DDL.
The issue is most likely with the text columns
CREATE External TABLE [dbo].[tbl_threads_controlPanel_v](
...
[detailed_qry] [nvarchar](300) NULL,
[bottomup_qry] [nvarchar](300) NULL,
...
CREATE TABLE [dbo].[tbl_threads]
...
[detailed_qry] [text] NULL,
[bottomup_qry] [text] NULL,
...
P.s.
https://msdn.microsoft.com/en-us/library/ms187993.aspx
IMPORTANT! ntext, text, and image data types will be removed in a future version of SQL Server. Avoid using these data types in new development work, and plan to modify applications that currently use them. Use nvarchar(max), varchar(max), and varbinary(max) instead.

How to update my table where updated columns names stored in another table in SQL Server

I have table User with n columns that stores user information in it.
I have another table User_Edit_Changes that I use to temporarily store changes to table User in it so that after admin confirmation I update the actual table User with new values.
In table User_Edit_Changes, I stored which user column requested for update and what is new value for that. How to write a dynamic query to get just changed value columns and new value from User_Edit_Changes and update the User table?
here is my sample create table command ,
teacher stores infos,
Tbl_ProfessorRequest stores edit change request,
Tbl_ProfessorEditInfoFields stores which fileds teacher request to edit
CREATE TABLE [dbo].[Teacher](
[code_ostad] [numeric](18, 0) NOT NULL,
[name] [varchar](30) NULL,
[family] [varchar](40) NOT NULL,
[namep] [varchar](30) NULL,
[idmadrak] [numeric](18, 0) NULL,
[namemadrak] [varchar](50) NULL,
[idresh] [numeric](18, 0) NULL,
[nameresh] [varchar](50) NULL,
[martabeh] [numeric](18, 0) NULL,
[namemartabeh] [varchar](30) NULL,
[nahveh_hamk] [numeric](18, 0) NULL,
CREATE TABLE [Request].[Tbl_ProfessorRequest](
[ProfessorRequestID] [int] IDENTITY(1,1) NOT NULL,
[Code_Ostad] [int] NULL,
[RequestTypeID] [bigint] NULL,
[RequestLogID] [bigint] NULL,
[CreateDate] [nvarchar](10) NULL,
[Note] [nvarchar](1000) NULL,
[term] [nvarchar](8) NULL,
[ProfessorMessage] [nvarchar](1000) NULL,
[Erae_Be] [nvarchar](100) NULL,
[ChangeSet] [int] NULL,
[isdeleted] [bit] NOT NULL,
[ScanImageUrl] [nvarchar](300) NULL,
CREATE TABLE [Request].[Tbl_ProfessorEditInfoFields](
[Id] [int] IDENTITY(1,1) NOT NULL,
[code_ostad] [int] NOT NULL,
[teacher_Column_Name] [nvarchar](200) NULL,
[OldValue] [nvarchar](200) NULL,
[NewValue] [nvarchar](200) NULL,
[State] [int] NOT NULL,
[ProfessorRequestID] [int] NOT NULL,
I'd say you have 3 options:
Handle the logic of updates outside the database, in what ever your application is built with. That's most likely the easiest way, since this kind of dynamic handling is not what databases are good at.
Build a dynamic SQL clause based on the contents of User_Edit_Changes. Loop through the changes in the table, construct an update statement into a variable and use sp_executesql to execute it. With cursor the code should be something like this:
set #params = N'#NewValue varchar(100)'
fetch next from yourcursor into #FieldName, #NewValue
while ##FETCH_STATUS = 0 begin
set #sql = 'update User set ' + #FieldName + ' = #NewValue'
exec sp_executesql #sql, #params, #NewValue = #NewValue
fetch next from yourcursor into #FieldName, #NewValue
end
Create static SQL statements for updating each of the columns. You can build something like this:
update U
set U.UserName = C.NewValue
from
User U
join User_Edit_Changes C on U.UserId = C.UserId
where
C.FieldName = 'UserName'
For this you of course need to have similar statements for each of your columns. You could build one massive update query with pivot or max+case, but handling the old and new values gets pretty complex.

create table fails in loop (SQL Server)

I have a sql script that creates tables for each db in my sql server. However it fails on one create table script. Eg the
CREATE TABLE [dbo].[Mx_Poll_Tags]
command. What is wrong with this? I don't see it.
The weird part is when I one by one run the scripts in a query window they all work fine. Only is this particular proc it fails.
The error states:
Msg 173, Level 15, State 1, Line 71
The definition for column 'Unit' must include a data type.
The create script is made by SQL Server itself by scripting an existing Mx_Poll_Tags table as CreateTo.
Does anyone see what the error is?
BEGIN
declare #proc nvarchar(max)
set #proc='if ''?'' like ''Client_%''
begin
use [?]
print ''?''
DROP TABLE [dbo].[ManualMetersInput]
DROP TABLE [dbo].[ManualMeterActions]
DROP TABLE [dbo].[ManualMeters]
DROP TABLE [dbo].[MX_Poll]
--DROP TABLE [dbo].[Mx_Poll_Tags]
DROP TABLE [dbo].[MX_Poll_Info]
DROP TABLE [dbo].[MX_Poll_Logs]
DROP TABLE [dbo].[MX_Poll_QA]
--DROP TABLE [dbo].[MX_Poll_Vars]
CREATE TABLE [dbo].[ManualMeters]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Ean] [varchar](max) NULL,
[Period] [int] NULL,
[TagTable] [varchar](max) NULL,
[TagTableId] [varchar](max) NOT NULL,
[Overflow] [int] NULL,
[TZ] [varchar](max) NULL,
) ON [PRIMARY]
CREATE TABLE [dbo].[ManualMetersInput]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Timestamp] [datetime2](7) NOT NULL,
[ManualMeterId] [int] NOT NULL,
[Value] [decimal](18, 3) NOT NULL,
[IsOverflow] [bit] NOT NULL,
[ImportDate] [datetime2](7) NOT NULL,
) ON [PRIMARY]
CREATE TABLE [dbo].[ManualMeterActions]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[ManualMeterId] [int] NOT NULL,
[UserId] [int] NOT NULL,
[Type] [nvarchar](max) NOT NULL,
) ON [PRIMARY]
CREATE TABLE [dbo].[MX_Poll]
(
[timestamp] [datetime2](7) NOT NULL,
[localtimestamp] [datetime2](7) NOT NULL,
) ON [PRIMARY]
CREATE TABLE [dbo].[MX_Poll_Info]
(
[timestamp] [datetime2](7) NOT NULL,
[info] [nvarchar](max) NOT NULL,
) ON [PRIMARY]
CREATE TABLE [dbo].[MX_Poll_Logs]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[timestamp] [datetime2](7) NOT NULL,
[Message] [nvarchar](max) NULL,
) ON [PRIMARY]
CREATE TABLE [dbo].[MX_Poll_QA]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[timestamp] [datetime2](7) NOT NULL,
[tag] [nvarchar](max) NULL,
[QA] [int] NULL
) ON [PRIMARY]
-- error here
CREATE TABLE [dbo].[Mx_Poll_Tags]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](800) NOT NULL,
[Unit] [int] NOT NULL,
[FieldName] [nvarchar](100) NULL,
[ScaleFromMin] [decimal](18, 3) NULL,
[ScaleFromMax] [decimal](18, 3) NULL,
[ScaleToMin] [decimal](18, 3) NULL,
[ScaleToMax] [decimal](18, 3) NULL,
[DeltaOfKwhCounter_Id] [int] NULL,
[Visible] [int] NULL,
[Type] [nvarchar](50) NULL,
[Enable] [int] NULL,
[Content] [int] NULL,
[Quantity] [int] NULL,
[Signal] [int] NULL,
[SignalDescription] [nvarchar](max) NULL,
[Connection] [nvarchar](max) NULL,
[Cable] [nvarchar](max) NULL,
[Comments] [nvarchar](max) NULL,
[UsedForPrediction_0] [bit] NOT NULL,
[RelatedToPrediction_0] [bit] NOT NULL,
[CalculatedByPredictionNo] [int] NULL,
) ON [PRIMARY]
end';
--print #proc;
exec sp_MSForEachDB #proc
END
GO
Can you try it with just creating that table?
Also, can you eliminate the "begin" and "end"? Based on this thread: http://www.sqlservercentral.com/Forums/Topic808714-8-1.aspx
I don't have enough reputation to make this a comment.
EDIT:
By default, sys.sp_MSforeachdb #command1 has a parameter length of nvarchar(2000). Even though you're passing in a varchar(max), anything over 2000 is being truncated.

Forgot to add primary key column as Identity

I had created a table like this
CREATE TABLE [dbo].[sydShopOrder](
[rowNumber] [varchar](50) NULL,
[firstName] [varchar](50) NULL,
[lastName] [varchar](50) NULL,
[employeeNumber] [varchar](50) NULL,
[productID] [varchar](50) NULL,
[shopID] [varchar](50) NULL,
[location] [varchar](50) NULL,
[address] [varchar](50) NULL,
[department] [varchar](50) NULL,
[datestamp] [date] NULL
) ON [PRIMARY]
I was intended to make [rowNumber] as primary key and make it identity column with auto increment. But I forgot to do it. And now the database is up and running in live environment. I had found this bug very late. Is there any way that I can fix this? Make [rowNumber] column as identity and auto increment it?
Current screenshot of table looks like this
You can drop [rownumber] and then add with identity
Alter Table [dbo].[sydShopOrder] Drop Column rownumber
Go
Alter Table [dbo].[sydShopOrder]
Add rownumber Int Identity(1, 1)
Go
If you want to populate the identity field for existing data, better to create another temporary table, and keep all the records of [dbo].[sydShopOrder] in that. After that truncate [dbo].[sydShopOrder] and then insert the values from that temp table to [dbo].[sydShopOrder]
CREATE TABLE #temp ([firstName] [varchar](50) NULL,
[lastName] [varchar](50) NULL,
[employeeNumber] [varchar](50) NULL,
[productID] [varchar](50) NULL,
[shopID] [varchar](50) NULL,
[location] [varchar](50) NULL,
[address] [varchar](50) NULL,
[department] [varchar](50) NULL,
[datestamp] [date] NULL)
INSERT INTO #temp
SELECT [firstName],[lastName],[employeeNumber],
[productID], [shopID],[location],
[address],[department],[datestamp]
FROM [dbo].[sydShopOrder]
TRUNCATE TABLE [dbo].[sydShopOrder]
INSERT INTO [dbo].[sydShopOrder]
SELECT * FROM #temp
Here is a sample SQLFIDDLE