Google Custom Search
Saturday, November 28, 2009
Consolidating our blogs into one website
Saturday, October 10, 2009
The Unhealthy Argument
This post of mine is 100 percent a personal opinion and was written not to hurt anyone.
Off late, I have been hearing or knowing incidents which have involved 2 or more persons going into an argument on deciding which technology is the best is it WINDOWS or UNIX, ORACLE or SQL SERVER, .Net or JAVA, IE or Chrome, etc. There are few incidents that came to my notice which I would like to share with you all.
1. This was between friends of mine who worked in my previous company; they both work in the same team providing support to one of their clients. One is an ORACLE DBA and other is SQL Server DBA. They have argued hardly to decide which Database systems is the best and have ended up criticizing Larry Ellison and Bill Gates.
2. The next is between the web browsers, I have read a numerous articles in the blogs and other websites saying IE is the best or Chrome is the best or Firefox is the best, etc. The same has happened between my known persons where they have ended using abusive languages. I am sorry to say this, but when people lose temper that is the end result.
3. Again, between my old colleagues, about WINDOWS or UNIX, each of them have had strong points to prove that they work on the latest technology of the server side Operating systems but failed to convince others. Thank God, NO blows or words were exchanged in the incident.
Now, let me come to say this, each technology or application is designed for a purpose and has its own pros and cons with it. Thanks to my patience in the recent past that I have not had such an Unhealthy Argument like this. In my opinion, a Database or an Operating system is chosen with the needs of the application or the system to be designed. It comes as a decision on that has to be compatible with the end application to be designed. The architect who decides on what needs to be used is not a biased person, he/she knows that he has to be committed to his company's core business values and chooses one deciding on it.
So, people going forth I request each of you not to have a discussion or argument to decide which the best is. We all work on the latest technologies of what we have now and should be proud that most of us are redefining technology that has got us in the past.
Again, this is a personal opinion and was written not to hurt anyone. Thanks for taking time to read this blog. Your comments on the same are welcome.
Thursday, October 1, 2009
Back to Blogging
Tuesday, August 18, 2009
Out for Vacation
Thursday, August 13, 2009
Virtual TechDays: FREE Technical Training Opportunity
Microsoft is Offering Free SQL Server and other products Techinical training in India. This is an online event. Please use the link below to register.
Tuesday, August 4, 2009
Chennai SQL Server User Group Meeting
Wednesday, July 1, 2009
Awarded MVP Again
Krishna Gopalan - KG, I wish to be near you to share the joy this moment. I can still hear you saying "Sugesh, I know you are the right person to do this job", whenever I heard that gave me confidence to enrich my skills as a DBA helping me to achieve near expertise.
Stephen Seth, Vidhya Sagar and Deepak - It is with these guys that I grew up enriching my SQL Server skills. Without them, I would still be a DBA not a MVP.
I would like to thank my friends Dalavai Shanmugha Sundaram, Mr&Mrs. Stephen Seth, Mr&Mrs. Arun Kamaraj, Chakravarthi Elangovan and Poornima rangaswamy for being with me during this tough days of personal and professional career.
A special mention of thanks to Rangaswamy and Rani Thilagam Rangaswamy for shouldering my responsibilities in India when I stay in USA.
And my parents and sister, I have no words to thank them. Without thier support and encouragement I would not have got this again.
Wednesday, June 10, 2009
Creating System Objects in SQL Server
sp_MS_marksystemobject 'object_name'
Saturday, May 9, 2009
Tuesday, April 21, 2009
Drive Details using TSQL
Thursday, April 16, 2009
Determine which objects exist in a particular filegroup
Tuesday, April 14, 2009
How to find startup procedures in sql
USE MASTER
GO
SELECT VALUE, VALUE_IN_USE, DESCRIPTION FROM SYS.CONFIGURATIONS WHERE NAME = 'scan for startup procs'GO
Wednesday, April 8, 2009
SQL Server 2008 SP1 released
Drop Indexes in a Database
Tuesday, April 7, 2009
Change Data Capture
Step to Enable and Configure Change Data Capture:
1. Create a database SQL Server 2008
create database CDC_TEST
go
2. Enable CDC in the database created.
USE SQL2008CDC
GO
EXEC sp_cdc_enable_db
GO
You can verify if CDC is enabled using the query below for the database.
select [name] as DBName,is_cdc_enabled from sys.databases where db_name(database_id)=DB_NAME()
3. You will be a new schema CDC and few system tables created under the database. Change Data Capture requires exclusive use of cdc user and schema.
4. Create a table to enable CDC
USE CDC_TEST
GO
CREATE TABLE dbo.CDC_TEST(
ID int Primary Key NOT NULL,
Name nvarchar(100) NOT NULL,
Email nvarchar(100) NOT NULL)
5. SQL Server agent must be started for CDC.
6. Enable CD for the table where you need to capture the change.
EXEC sp_cdc_enable_table 'dbo', 'cdc_test',
@role_name = NULL, @supports_net_changes =1
You can verify if CDC is enabled using the query below for the table.
use SQL2008CDC
go
select [name], is_tracked_by_cdc from sys.tables
7. Once CDC is enabled for a table, you will find a _CT table created by itself.
8. Now we will verify how CDC works by running a insert into the table CDC_TEST.
use SQL2008CDC
go
INSERT INTO dbo.cdc_test
values (1, N'sugeshkumar', N'sugeshkr@gmail.com')
9. Now update the row that we have inserted in the previous step.
use SQL2008CDC
go
update dbo.cdc_test set name='sugesh' where id = 1
10. The before image and after image of the row can be found on the table that was created with the name _CT.
The column _$operation has the value for the DML operation done, 1 is for delete, 2 for insert, 3 for before image, 4 for after image
You have seen how to enable and configure CDC for a database and table. The list below gives you all available Stored Procedures, DMVs, Functions and table list that is used by Change Data Capture.
Stored Procedures
sys.sp_cdc_add_job (Transact-SQL)
sys.sp_cdc_generate_wrapper_function (Transact-SQL)
sys.sp_cdc_change_job (Transact-SQL)
sys.sp_cdc_get_captured_columns (Transact-SQL)
sys.sp_cdc_cleanup_change_table (Transact-SQL)
sys.sp_cdc_get_ddl_history (Transact-SQL)
sys.sp_cdc_disable_db (Transact-SQL)
sys.sp_cdc_help_change_data_capture (Transact-SQL)
sys.sp_cdc_disable_table (Transact-SQL)
sys.sp_cdc_help_jobs (Transact-SQL)
sys.sp_cdc_drop_job (Transact-SQL)
sys.sp_cdc_scan (Transact-SQL)
sys.sp_cdc_enable_db (Transact-SQL)
sys.sp_cdc_start_job (Transact-SQL)
sys.sp_cdc_enable_table (Transact-SQL)
sys.sp_cdc_stop_job (Transact-SQL)
Dynamic Management Views
sys.dm_cdc_log_scan_sessions (Transact-SQL)
sys.dm_cdc_errors (Transact-SQL)
sys.dm_repl_traninfo (Transact-SQL)
Tables
cdc.
Returns one row for each change made to a captured column in the associated source table.
cdc.captured_columns
Returns one row for each column tracked in a capture instance.
cdc.change_tables
Returns one row for each change table in the database.
cdc.ddl_history
Returns one row for each data definition language (DDL) change made to tables that are enabled for change data capture.
cdc.lsn_time_mapping
Returns one row for each transaction having rows in a change table. This table is used to map between log sequence number (LSN) commit values and the time the transaction committed.
cdc.index_columns
Returns one row for each index column associated with a change table.
dbo.cdc_jobs (Transact-SQL)
Returns the configuration parameters for change data capture agent jobs
Functions
cdc.fn_cdc_get_all_changes_
sys.fn_cdc_has_column_changed (Transact-SQL)
cdc.fn_cdc_get_net_changes_
sys.fn_cdc_increment_lsn (Transact-SQL)
sys.fn_cdc_decrement_lsn (Transact-SQL)
sys.fn_cdc_is_bit_set (Transact-SQL)
sys.fn_cdc_get_column_ordinal (Transact-SQL)
sys.fn_cdc_map_lsn_to_time (Transact-SQL)
sys.fn_cdc_get_max_lsn (Transact-SQL)
sys.fn_cdc_map_time_to_lsn (Transact-SQL)
sys.fn_cdc_get_min_lsn (Transact-SQL)
Monday, April 6, 2009
Generate Create Index Scripts for a Database
DECLARE cIX CURSOR FOR
SELECT OBJECT_NAME(SI.Object_ID), SI.Object_ID, SI.Name, SI.Index_ID
FROM Sys.Indexes SI
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC ON SI.Name = TC.CONSTRAINT_NAME AND OBJECT_NAME(SI.Object_ID) = TC.TABLE_NAME
WHERE TC.CONSTRAINT_NAME IS NULL
AND OBJECTPROPERTY(SI.Object_ID, 'IsUserTable') = 1
ORDER BY OBJECT_NAME(SI.Object_ID), SI.Index_ID
DECLARE @IxTable SYSNAME
DECLARE @IxTableID INT
DECLARE @IxName SYSNAME
DECLARE @IxID INT
-- Loop through all indexes
OPEN cIX
FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID
WHILE (@@FETCH_STATUS = 0)
BEGIN
DECLARE @IXSQL NVARCHAR(4000) SET @IXSQL = ''
SET @IXSQL = 'CREATE '
-- Check if the index is unique
IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsUnique') = 1)
SET @IXSQL = @IXSQL + 'UNIQUE '
-- Check if the index is clustered
IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsClustered') = 1)
SET @IXSQL = @IXSQL + 'CLUSTERED '
SET @IXSQL = @IXSQL + 'INDEX ' + @IxName + ' ON ' + @IxTable + '('
-- Get all columns of the index
DECLARE cIxColumn CURSOR FOR
SELECT SC.Name
FROM Sys.Index_Columns IC
JOIN Sys.Columns SC ON IC.Object_ID = SC.Object_ID AND IC.Column_ID = SC.Column_ID
WHERE IC.Object_ID = @IxTableID AND Index_ID = @IxID
ORDER BY IC.Index_Column_ID
DECLARE @IxColumn SYSNAME
DECLARE @IxFirstColumn BIT SET @IxFirstColumn = 1
-- Loop throug all columns of the index and append them to the CREATE statement
OPEN cIxColumn
FETCH NEXT FROM cIxColumn INTO @IxColumn
WHILE (@@FETCH_STATUS = 0)
BEGIN
IF (@IxFirstColumn = 1)
SET @IxFirstColumn = 0
ELSE
SET @IXSQL = @IXSQL + ', '
SET @IXSQL = @IXSQL + @IxColumn
FETCH NEXT FROM cIxColumn INTO @IxColumn
END
CLOSE cIxColumn
DEALLOCATE cIxColumn
SET @IXSQL = @IXSQL + ')'
-- Print out the CREATE statement for the index
PRINT @IXSQL
FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID
END
CLOSE cIX
DEALLOCATE cIX
-- Get all existing primary keys
DECLARE cPK CURSOR FOR
SELECT TABLE_NAME, CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
ORDER BY TABLE_NAME
DECLARE @PkTable SYSNAME
DECLARE @PkName SYSNAME
-- Loop through all the primary keys
OPEN cPK
FETCH NEXT FROM cPK INTO @PkTable, @PkName
WHILE (@@FETCH_STATUS = 0)
BEGIN
DECLARE @PKSQL NVARCHAR(4000) SET @PKSQL = ''
SET @PKSQL = 'ALTER TABLE ' + @PkTable + ' ADD CONSTRAINT ' + @PkName + ' PRIMARY KEY CLUSTERED ('
-- Get all columns for the current primary key
DECLARE cPKColumn CURSOR FOR
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_NAME = @PkTable AND CONSTRAINT_NAME = @PkName
ORDER BY ORDINAL_POSITION
OPEN cPKColumn
DECLARE @PkColumn SYSNAME
DECLARE @PkFirstColumn BIT SET @PkFirstColumn = 1
-- Loop through all columns and append the sql statement
FETCH NEXT FROM cPKColumn INTO @PkColumn
WHILE (@@FETCH_STATUS = 0)
BEGIN
IF (@PkFirstColumn = 1)
SET @PkFirstColumn = 0
ELSE
SET @PKSQL = @PKSQL + ', '
SET @PKSQL = @PKSQL + @PkColumn
FETCH NEXT FROM cPKColumn INTO @PkColumn
END
CLOSE cPKColumn
DEALLOCATE cPKColumn
SET @PKSQL = @PKSQL + ')'
-- Print the primary key statement
PRINT @PKSQL
FETCH NEXT FROM cPK INTO @PkTable, @PkName
END
CLOSE cPK
DEALLOCATE cPK
Friday, April 3, 2009
Common SQL Server Security Issues and Solutions
Thursday, April 2, 2009
Show/Hide divs and swap images with SkinID using Javascript
Example 1: To Show only one div at a time.
ASP.Net Code
<div id="divContent">JavaScript Code:
<h2><a href="#" id="lnk1" onclick="return toggle('div1')">What is Test?</a></h2>
<div id="div1" style="display:none">
<p>Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test</p>
<p>Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test</p>
</div>
<h2><a href="#" id="lnk8" onclick="return toggle('div8')">What is Sample?</a></h2>
<div id="div8" style="display:none">
<p>Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample </p>
</div>
</div>
function toggle(divID)
{
var divToShow = document.getElementById(divID);
var divUL = document.getElementById('dvfaq');
var divs = divUL.getElementsByTagName('DIV');
for(var i = 0; i < divs.length; i++)
{
divs[i].style.display = 'none';
if(divToShow.style.display == 'none')
{
divToShow.style.display = 'block';
}
}
return false;
}
Example 2: To Show multiple divs at a time and click to open and close.
ASP.Net Code
<a id="lnk0" href="#" onclick="return toggle('div0', 'lnk0')">
Q: What is Test? <asp:Image ID="imgToggle" SkinID="ArrowClose"
style="display: inline" runat="server" /><asp:Image ID="Image27"
SkinID="ArrowOpen" style="display: none" runat="server" /></a>
<br />
<div id="div0" style="display:none">
<p>A: Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test
Test Test Test Test Test Test </p>
</div>
<a id="lnk1" href="#" onclick="return toggle('div1', 'lnk1')">
Q: What is Sample? <asp:Image ID="Image1" SkinID="ArrowClose"
style="display: inline" runat="server" /><asp:Image ID="Image28"
SkinID="ArrowOpen" style="display: none" runat="server" /></a>
<br />
<div id="div1" style="display:none">
<p> Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample Sample Sample Sample
Sample Sample Sample Sample </p>
</div>
JavaScript Code:
function toggle(divID, imgID)
{
var divToShow = document.getElementById(divID);
if(divToShow.style.display == 'none')
{
divToShow.style.display = 'block';
}
else if(divToShow.style.display == 'block')
{
divToShow.style.display = 'none';
}
var imgToShow = document.getElementById(imgID).getElementsByTagName('img')[0];
var imgToHide = document.getElementById(imgID).getElementsByTagName('img')[1];
if(imgToShow.style.display == 'none')
{
imgToShow.style.display = 'inline';
imgToHide.style.display = 'none';
}
else if(imgToShow.style.display == 'inline')
{
imgToShow.style.display = 'none';
imgToHide.style.display = 'inline';
}
return false;
}
Skin Code:
<asp:Image runat="server" SkinID="ArrowClose" ImageUrl="images/arrowClose.gif"
width="9" height="9" />
<asp:Image runat="server" SkinID="ArrowOpen" ImageUrl="images/arrowOpen.gif"
width="9" height="9" />
Wednesday, April 1, 2009
Migrating Access Database to SQL Server
To Migrate Access to SQL Server database, download the tool SQL Server Migration Assistant for Access
Install SQL Server Migration Assistant for Access on local computer
You need to have the access database closed while migrating to SQL Server.
Goto Start->;Programs->;Microsoft SQL Server Migration Assistant 2008 for Access->;Microsoft SQL Server Migration Assistant 2008 for Access from the computer where it's installed. You will see the welcome screen.
Click Next, Create a new project by entering the Name of the project and it's location. Click Next, You will be taken to a screen to add the Access database. Click on Add Databases button to specify the folder where your access database resides.
Click Next, Here you will have option to migrate only data and/or the queries too. Here, we are migrating both data and the queries.
Click Next, You will see the SQL Server connection Screen. Here specify the SQL Server instance where you want to move your Access database along with the destination Database name and credentials.
Click Next to Link tables. If you want to use your existing Access applications with SQL Server, you can link your original Access tables to the migrated SQL Server tables. Linking modifies your Access database so that your queries, forms, reports, and data access pages use the data in the SQL Server database instead of the data in your Access database.
You will see the objects and queries to be migrated. Here If there are any errors or discrepencies will also notified.
Click Ok to complete migration.
Now, you can open your SQL Server database to see that the Access tables and Queries are migrated. The Queries will be migrated as Views and you can use them as you did in the Access tables. The migration task is simple than expected. Now the next task that you will learn from me on this is HOW TO MIGRATE ACCESS REPORTS TO SQL SERVER?
Saturday, March 28, 2009
Database Size Info
declare @dbname sysname
set nocount on
if @dbname is not null and @dbname not in (select name from sysdatabases (nolock))
begin
raiserror('Incorrect database name. ', 16, 1)
end
create table #datafilestats
( dbname varchar(25),
flag bit default 0,
Fileid tinyint,
[FileGroup] tinyint,
TotalExtents dec (8, 1),
UsedExtents dec (8, 1),
[Name] varchar(50),
[FileName] sysname )
declare @string sysname, @dbname1 sysname
set @string = ''
if @dbname is not null
set @dbname1 = @dbname
else
set @dbname1 = ''
set @dbname = ''
while 1=1
begin
select top 1 @dbname = name from master..sysdatabases where name > @dbname --order by name asc
if @@rowcount = 0
break
set @string = 'use ' + @dbname + ' DBCC SHOWFILESTATS with no_infomsgs'
insert into #datafilestats (Fileid, [FileGroup] , TotalExtents , UsedExtents , [Name] , [FileName]) exec (@string)
update #datafilestats set dbname = @dbname, flag = 1 where flag = 0
update #datafilestats set TotalExtents = (select sum(TotalExtents)*8*8192.0/1048576.0 from #datafilestats where dbname = @dbname)
where flag = 1 and Fileid = 1 and FileGroup = 1 and dbname = @dbname
update #datafilestats set UsedExtents = (select sum(UsedExtents)*8*8192.0/1048576.0 from #datafilestats where dbname = @dbname)
where flag = 1 and Fileid = 1 and FileGroup = 1 and dbname = @dbname
end
create table #sizeinfo
( db_name varchar(30) not null primary key clustered,
total dec (7, 1),
data dec (7, 1),
data_used dec (7, 1),
[data (%)] dec (7, 1),
data_free dec (7, 1),
[data_free (%)] dec (7, 1),
log dec (7, 1),
log_used dec (7, 1),
[log (%)] dec (7, 1),
log_free dec (7, 1),
[log_free (%)] dec (7, 1),
status dec (7, 1) )
insert #sizeinfo (db_name, log, [log (%)], status ) exec ('dbcc sqlperf(logspace) with no_infomsgs')
update #sizeinfo set
data = d.TotalExtents from #datafilestats d join #sizeinfo s on d.dbname = s.db_name where d.flag = 1 and d.Fileid = 1 and d.FileGroup = 1
update #sizeinfo set
data_used = d.UsedExtents from #datafilestats d join #sizeinfo s on d.dbname = s.db_name where d.flag = 1 and d.Fileid = 1 and d.FileGroup = 1
update #sizeinfo set
total = (data + log)
update #sizeinfo set
[data (%)] = (data_used * 100.0 / data)
update #sizeinfo set
data_free = (data - data_used)
update #sizeinfo set
[data_free (%)] = (100 - [data (%)])
update #sizeinfo set
log_used = (log * [log (%)] / 100.0)
update #sizeinfo set
log_free = (log - log_used)
update #sizeinfo set
[log_free (%)] = (log_free * 100.0 / log)
print ''
if @dbname1 = ''
begin
print 'Database size report on ' + @@servername + ' as of ' + convert(varchar(30), getdate(), 100) + char(10)
select db_name,
total,
data,
data_used,
[data (%)],
data_free,
[data_free (%)],
log,
log_used,
[log (%)],
log_free,
[log_free (%)]
from #sizeinfo order by db_name asc compute sum(total)
end
else
begin
print 'Database size report on ' + @@servername + '.' + @dbname1 + ' as of ' + convert(varchar(30), getdate(), 100) + char(10)
select db_name,
total,
data,
data_used,
[data (%)],
data_free,
[data_free (%)],
log,
log_used,
[log (%)],
log_free,
[log_free (%)]
from #sizeinfo where db_name = @dbname1
end
go
drop table #datafilestats
drop table #sizeinfo
Thursday, March 26, 2009
Job Schedule Information for SQL Server 2005
Wednesday, March 25, 2009
Database Details
create table #dbdetails(name varchar(30), fileid int,filename varchar(1000), filegroup varchar(50), size varchar(30), maxsize varchar(30), growth varchar(30), usage varchar(30))
insert into #dbdetails
EXEC sp_MSforeachdb 'USE [?]; EXEC sp_helpfile;'
select * from #dbdetails
drop table #dbdetails
Tuesday, March 24, 2009
Job Status Script
select b.name,a.step_name,
c.message,
case c.run_status when 0 then 'Failed'
when 1 then 'Succeeded'
when 2 then 'Retry'
when 3 then 'Canceled'
when 4 then 'In progress'
else 'NO STATUS' END as status
,substring (right (stuff (' ', 1, 1, '000000') + convert(varchar(6),c.run_time), 6), 1, 2)
+ ':'
+ substring (
right (stuff (' ', 1, 1, '000000') + convert(varchar(6), c.run_time), 6) ,3 ,2)
+ ':'
+ substring (
right (stuff (' ', 1, 1, '000000') + convert(varchar(6),c.run_time), 6) ,5 ,2) as run_time
,substring (right (stuff (' ', 1, 1, '00000000') + convert(varchar(8),c.run_date), 8), 1, 4)
+ '/'
+ substring (
right (stuff (' ', 1, 1, '00000000') + convert(varchar(8), c.run_date), 8) ,5 ,2)
+ '/'
+ substring (
right (stuff (' ', 1, 1, '00000000') + convert(varchar(8),c.run_date), 8) ,7 ,2) as run_date
from msdb..sysjobsteps a, msdb..sysjobhistory c,msdb..sysjobs b
where a.step_id=c.step_id and a.job_id=c.job_id
and
a.last_run_date=c.run_date
and
a.last_run_time=c.run_time
and a.job_id=b.job_id
Monday, March 23, 2009
Script to Validate Subscribers for all articles and publication
declare @artobj nvarchar(100)
declare @owner nvarchar(50)
declare @params nvarchar(100)
declare @cnt1 nvarchar(50)
declare @cmd nvarchar(1000)
declare @cmd1 nvarchar(1000)
DECLARE pub_validate CURSOR FOR
select publisher_db,source_owner,source_object from distribution.dbo.MSarticles
open pub_validate
fetch next from pub_validate into @pubdb,@owner,@artobj
while @@fetch_status=0
begin
select @cmd = 'select @cnt=count(*) from '+@pubdb+'.'+@owner+'.'+@artobj
select @params=N'@cnt varchar(100) OUTPUT'
exec sp_executesql @cmd,@params,@cnt=@cnt1 output
--select @cnt1
select @cmd1='use '+@pubdb+CHAR(10)+'go'+CHAR(10)+'sp_table_validation @table='+@artobj+',@expected_rowcount='+@cnt1
select @cmd1
--exec sp_executesql @cmd1
fetch next from pub_validate into @pubdb,@owner,@artobj
end
close pub_validate
deallocate pub_validate
Cross-Domain Windows Authentication for SQL Server databases
Consider one of the servers is in new york domain and Second is in boston domain. newyork domain can't talk to boston domain and vice versa..The idea is to make the windows user in newyork domain access database in boston domain using the same windows credentials. This can be achieved by following steps below.
1. Create a SQL login named sqluser in the secondary server and copy the sid of the login.
2. Create a login in the primary named sqluser with sid captured.
CREATE LOGIN sqluser with PASSWORD='sqluser1', SID = 0xB0B50710A1D1394D8E1B26CFA25AA3BE
--- copied from secondary server.
Assign the datareader permissions to primary server.
3. This user will be replicated to the secondary readonly db through log backup, being sid matches between the user and login named sqluser, it works.
It’s simple, no downtime required.
Windows Authentication: (user named newyork\sqluser)
It’s the same but we may have to work thru some tricky steps. Reason behind was that Windows domain account will have a unique SID value.
1. Create a windows login named newyork\sqluser in the secondary server. Copy the sid.
2. Create a login in the primary named sqluser with sid captured
CREATE LOGIN sqluser with PASSWORD='sqluser123', SID = 0x01050000000000051500000071416F0BD9618A1FC22E626EC6190003
it results with the below error..
Msg 15419, Level 16, State 1, Line 1
Supplied parameter sid should be binary(16).
3. Basic and logic helps here. Create a login named sqluser in the Primary with the datareader permissions.
CREATE LOGIN sqluser with PASSWORD='sqluser123'
4. Now the user named sqluser is replicated to the secondary readonly db but stands as a orphaned user. It’s not in sync with the windows login(newyork\sqluser).
5. whats the next option.. how do we bring the sid in sync now.
Use SQLCMD with DAC session on primary server
c:\> SQLCMD -A -d master
-A - options opens DAC(admin session)
SQLCMD>
Enable the allow updates option using sp_configure and update the sid of the sqluser login in sys.sysusers table with sid of windows login(newyork\sqluser)
This query results with an error because updates can be happened only when db is in single user mode with sql 2005.
C:\>sqlcmd -A
1> sp_configure 'allow updates'
2> go
name minimum maximum config_value run_value
----------------------------------- ----------- ----------- ------------ -----------
allow updates 0 1 1 1
1> update sys.sysusers set sid = 0xB0B50710A1D1394D8E1B26CFA25AA3BE where name like 'sqluser'
2> Go
Msg 259, Level 16, State 1, Server servername, Line 1
Ad hoc updates to system catalogs are not allowed.
1>exit
sid can be captured in sys.sysxlgns table also which are similar to sysxlogins in SQL 2000. It can be viewed only when you open a session using DAC. In order to update the system tables we have to bring sql server in single user mode.
sqlservr -m -- helps you to bring sql server in single user mode.
Repeat step 5 but sql server should be started with single user mode.
C:\>sqlcmd -A
1> use demo;
2> go
Changed database context to 'Demo'.
1> update sys.sysusers set sid = 0xD67EDAA0627B944F997EB9C552DEE47A where name like 'sqluser';
2> go
(1 rows affected)
Warning: System table ID 27 has been updated directly in database ID 6 and cache coherence may not have been maintained. SQL Server should be restarted.
Now it works. recycle the SQL.Log backup of primary database will update the sid of the sys.sysusers in the secondary db. Now the windows user will have the datareader permissions on the table..
Now newyork\sqluser will have readonly access to secondary db
Wednesday, March 18, 2009
Validating Replication Subscriber using TSQL
Last post from me on SQL Server replication was on How to validate subscribers in SQL Server Replication. This article shows how the same can be done using TSQL.
sp_publication_validation:
This system stored procedure does a validation for each and all articles in the specified publication in transactional replication. This stored procedure is executed against the publication database. The following is the syntax for this stored procedure.
sp_publication_validation [ @publication = ] 'publication'
[ , [ @rowcount_only = ] type_of_check_requested ]
[ , [ @full_or_fast = ] full_or_fast ]
[ , [ @shutdown_agent = ] shutdown_agent ]
[ , [ @publisher = ] 'publisher' ]
@publication is the name of the publication.
@rowcount_only is whether to return only the row count for the table.
0 for perform a SQL Server 7.0 compatible check sum
1 for perform rowcount only
2 for perform a row count and binary check sum.
@full_or_fast is used to calculate the row count.
0 does full count using count(*)
1 does a count using rows column in sysindexes table. Since this table is not updated frequently this might be wrong sometimes.
2 does a count using rows column in sysindexes table if there is a difference then it does a full count.
@shutdown_agent Specifies whether to shutdown distribution agent immediately after completing the validation.
@publisher specifies a non-sql server publisher.
You need to have sysadmin or db_owner role in the publication database to execute stored procedure.
sp_article_validation:
This system stored procedure does a validation for each article individually in the specified publication in transactional replication. This stored procedure is executed against the publication database. The following is the syntax for this stored procedure.
sp_article_validation [ @publication = ] 'publication'
[ , [ @article = ] 'article' ]
[ , [ @rowcount_only = ] type_of_check_requested ]
[ , [ @full_or_fast = ] full_or_fast ]
[ , [ @shutdown_agent = ] shutdown_agent ]
[ , [ @subscription_level = ] subscription_level ]
[ , [ @reserved = ] reserved ]
[ , [ @publisher = ] 'publisher' ]
@publication is the name of the publication in which the article exists.
@article is the name of the article to validate.
@rowcount_only specifies if only the rowcount for the table is returned.
0 for perform a rowcount and a Microsoft SQL Server 7.0 compatible checksum.
1 for perform a rowcount check only.
2 for perform a rowcount and binary checksum.
@full_or_fast is the method used to calculate the rowcount.
0 does full count using count(*)
1 does a count using rows column in sysindexes table. Since this table is not updated frequently this might be wrong sometimes.
2 does a count using rows column in sysindexes table if there is a difference then it does a full count.
@shutdown_agent Specifies whether to shutdown distribution agent immediately after completing the validation.
@subscription_level specifies whether or not the validation is picked up by a set of subscribers. If 0, validation is applied to all Subscribers. If 1, validation is only applied to a subset of the Subscribers specified by calls to sp_marksubscriptionvalidation in the current open transaction.
@reserved identified for informational purposes only.
@publisher specifies a non-Microsoft SQL Server Publisher.
You need to have SELECT ALL permissions on the source table for the article being validated
sp_table_validation:
This system stored procedure does a validation for each table individually in the specified publication in transactional replication. This stored procedure is executed against the publication database. The following is the syntax for this stored procedure.
sp_table_validation [ @table = ] 'table'
[ , [ @expected_rowcount = ] type_of_check_requested OUTPUT]
[ , [ @expected_checksum = ] expected_checksum OUTPUT]
[ , [ @rowcount_only = ] rowcount_only ]
[ , [ @owner = ] 'owner' ]
[ , [ @full_or_fast = ] full_or_fast ]
[ , [ @shutdown_agent = ] shutdown_agent ]
[ , [ @table_name = ] table_name ]
[ , [ @column_list = ] 'column_list' ]
@table is the name of the table to be validated.
@expected_rowcount specifies whether to return the expected number of rows in the table. If NULL, the actual rowcount is returned as an output parameter. If a value is provided, that value is checked against the actual rowcount to identify any differences.
@expected_checksum specifies whether to return the expected checksum for the table. If NULL, the actual checksum is returned as an output parameter. If a value is provided, that value is checked against the actual checksum to identify any differences.
@rowcount_only specifies what type of checksum or rowcount to perform.
0 for perform a rowcount and a Microsoft SQL Server 7.0 compatible checksum.
1 for perform a rowcount check only.
2 for perform a rowcount and binary checksum.
@owner is the name of the owner of the table.
@full_or_fast is the method used to calculate the rowcount.
0 does full count using count(*)
1 does a count using rows column in sysindexes table. Since this table is not updated frequently this might be wrong sometimes.
2 does a count using rows column in sysindexes table if there is a difference then it does a full count.
@shutdown_agent Specifies whether to shutdown distribution agent immediately after completing the validation.
@table_name is the table name of the view used for output messages.
@column_list is the list of columns that should be used in the checksum function.
Monday, March 16, 2009
My Interview in MVP Summit
Mike Nash from c-sharpconsulting interviewed me for a short duration of 2 minutes during the MVP summit. The link for the video is given below.
http://www.c-sharpcorner.com/UploadFile/mahesh/Vs03122009175026PM/Vs.aspx
How to validate subscribers in SQL Server Replication
There have been many SQL Server DBAs who would like to compare the row count between tables in replication Publisher and Subscriber. SQL Server provides an easy way of doing this and is known as validation subscribers in replication which involves doing a row count between the table that is published and the ones that are subscribed to it.
To Validate subscribers, you need to do the following.
- Launch replication monitor.
- Right click the publisher for which you want to validate the row count and click validate subscriptions.
- Choose the subscribers that you want to validate, by default it chooses all subscribers for that publication.
- You will be provided with the validation options.
- Select the validation option that best suits you. It is advisable to choose, "Compute a fast row count: If differences are found, compute an actual row count"
- Click ok.
- Click ok.
Now you will be able to see the row count match are mismatch between the publisher and the subscriber, when you double click the subscriber. The next article would be how to perform the same validation using TSQL.
Sunday, March 15, 2009
tablediff utility
Tablediff is an inbuilt SQL Server utility that is used to compare data between two tables across same or different servers. This utility is invoked from command prompt and is usually found in C:\Program Files\Microsoft SQL Server\100\COM folder. The best use of this utility is exhibited when you use it to compare tables that are involved in replication. The following tasks can be performed with the utility.
- A row by row comparison between a source table in an instance of Microsoft SQL Server acting as a replication Publisher and the destination table at one or more instances of SQL Server acting as replication Subscribers.
- Perform a fast comparison by only comparing row counts and schema.
- Perform column-level comparisons.
- Generate a Transact-SQL script to fix discrepancies at the destination server to bring the source and destination tables into convergence.
- Log results to an output file or into a table in the destination database.
Tablediff has various arguments that can be passed to it to get the desired results.
The parameters are discussed as follows.
-sourceserver source_server_name[\instance_name]
The name of the source server. You need to specify the source instance name to this argument.
-sourcedatabase source_database
The name of the source database.
-sourcetable source_table_name
The name of the source table being compared.
-sourceschema source_schema_name
The schema owner of the source table. By default, the table owner is dbo.
-sourcepassword source_password
The password for the login used to connect to the source server using SQL Server Authentication.
-sourceuser source_login
The login used to connect to the source server using SQL Server Authentication. If source_login is not supplied, the utility uses Windows Authentication to connect to the source server. Whenever possible, use Windows Authentication.
-sourcelocked
The source table is locked during the comparison using the TABLOCK and HOLDLOCK table hints.
-destinationserver destination_server_name[\instance_name]
The name of the destination server. You need to specify the source instance name to this argument.
-destinationdatabase subscription_database
The name of the destination database.
-destinationtable destination_table
The name of the destination table.
-destinationschema destination_schema_name
The schema owner of the destination table. By default, the table owner is dbo.
-destinationpassword destination_password
The password for the login used to connect to the destination server using SQL Server Authentication.
-destinationuser destination_login
The login used to connect to the destination server using SQL Server Authentication. If destination_login is not supplied, the utility uses Windows Authentication to the server. When possible, use Windows Authentication.
-destinationlocked
The destination table is locked during the comparison using the TABLOCK and HOLDLOCK table hints.
-b large_object_bytes
The number of bytes to compare for large object data type columns, which includes: text, ntext, image, varchar(max), nvarchar(max) andvarbinary(max). large_object_bytes defaults to the size of the column. Any data above large_object_bytes will not be compared.
-bf number_of_statements
The number of Transact-SQL statements to write to the current Transact-SQL script file when the -f option is used. When the number of Transact-SQL statements exceeds number_of_statements, a new Transact-SQL script file is created.
-c
Compare column-level differences.
-dt
Drop the result table specified by table_name, if the table already exists.
-et table_name
Specifies the name of the result table to create. If this table already exists, -DT must be used or the operation will fail.
-f [ file_name ]
Generates a Transact-SQL script to synchronize table that are being compared. You can optionally specify a name and path for the generated Transact-SQL script file.
-o output_file_name
The full name and path of the output file.
-q
Perform a fast comparison by only comparing row counts and schema.
-rc number_of_retries
Number of times that the utility retries a failed operation.
-ri retry_interval
Interval, in seconds, to wait between retries.
-strict
Source and destination schema are strictly compared.
-t connection_timeouts
Is the connection timeout period, in seconds, for connections to the source server and destination server.
Restrictions:
The source table in the comparison must contain at least one primary key, identity, or ROWGUID column. When you use the -strict option, the destination table must also have a primary key, identity, or ROWGUID column.
The Transact-SQL script generated to bring the destination table into convergence does not include the following data types:
- varchar(max)
- nvarchar(max)
- varbinary(max)
- timestamp
- xml
- text
- ntext
- image
Permissions Needed:
1. You need select permissions on the tables being compared.
2. To use the -et option, you must be a member of the db_owner fixed database role, or at least have CREATE TABLE permission in the subscription database and ALTER permission on the destination owner schema at the destination server.
3. To use the -dt option, you must be a member of the db_owner fixed database role, or at least have ALTER permission on the destination owner schema at the destination server.
4. To use the -o or -f options, you must have write permissions to the specified file directory location.