Rajib Bahar's Blog

Rajib blogs here about topics of his interest.

Set Operation trick to generate date data #TSQL2sDay

December 08
by Rajib Bahar 8. December 2009 17:52

Two things that happened today, which motivated me to write this post: 

1. I learned a new trick using set-operation

2. Also today is the day some of my SQL Server colleagues having #TSQL2sDay party

 

Here is the entry where I learned the trick [http://ask.sqlteam.com/questions/1206/insert-date-value-for-1-year]. 

 

I have been participating at AskSqlTeam.com lately. One of the recent question was about how to generate date for 1 year. TG had an interesting solution and I did not realize it was set-operation until Kristen set me straight. :) As usual, I was coming up with a iterative solution as opposed to set-based one. Here is the snippet I modified off of TG's code.

create table #myTable 
(dateCol datetime)
go
declare @i int
SET @i = 0
WHILE 
(
 datediff(year, dateadd(day, @i,'2010-01-01'),'2010-01-01')=0
)
begin
    insert #myTable (dateCol)
    select dateadd(day, @i, '2010-01-01')
    SET @i = @i + 1
    continue
end
go
select * from #myTable
go


The script above will create about 365 entries containing everyday of the year 2010. 

TG's answer to that problem was:

create table #myTable 
(dateCol datetime)
go
insert #myTable (dateCol)
select dateadd(day, number, '2010-01-01')
from   master..spt_values
where  type = 'P'and    number < 365
order by number
go
select * from #myTable
go

 

Anyways, my approach above is not the most ideal solution and it will be slow because of the looping. TG had the right idea. Many DB professional create a reference database for their tasks. In this database one may have scripts that can be applied on scheduled jobs and other artifacts that don't belong anywhere else. The solution above can be improved if we create a reference table containing all integers. Let's say we call that table IntValues. I started building that table today and it took more than 6 hours to enter 2 billion numbers. Here is the final draft of what that script would look like.

 

create table #myTable 
(dateCol datetime)
go
insert #myTable (dateCol)
select dateadd(day, number, '2010-01-01')
from   DbReference.dbo.IntValues
where  number < 365
order by number
go
select * from #myTable
go

Combining SMO and Powershell to Generate SQL Database Schema

December 08
by Rajib Bahar 8. December 2009 10:49

There are times we find the need to generate the database schema. In SQL Server, it can be easily done using the graphical wizards in the Management Studio. I haven't found a way to script it to this day.

 

However, one alternative solution to this is to combine .NET programmability feature in powershell, and SMO. With this approach you can setup a powershell script job to automate your team's database build process.

 

Here are some basic assumptions before reading this post:

1. SQL Server 2008 is installed

2. Powershell is installed

3. SMO is in the GAC (Global Assembly Cache) or you know how to register it there

4. AdventureWorks is loaded in the database

 

Here are the steps I took to generate script against AdventureWorks database:

 

First of all, I went to management studio and right clicked on the AdventureWorks database to "Start Powershell"

 

PS SQLSERVER:\SQL\OVERLORD\SQL2K8\Databases\AdventureWorks> [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")

GAC    Version        Location
---    -------        --------
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SqlServer.Smo\1...

 

At this point, the SMO object was loaded using .NET reflection technology. Next we declare $srv variable and assign the local SQL Server 2008 instance to it. Then we assign the AdventureWorks database to the $db variable. The database object has an overloaded method namely Script(). We need to invoke that method to generate the database script. See the output below as the script is run.

 

PS SQLSERVER:\SQL\OVERLORD\SQL2K8\Databases\AdventureWorks> $srv = new-object("Microsoft.SqlServer.Management.Smo.Server") "(local)\sql2k8"
PS SQLSERVER:\SQL\OVERLORD\SQL2K8\Databases\AdventureWorks> $db = $srv.Databases["AdventureWorks"]

PS SQLSERVER:\SQL\OVERLORD\SQL2K8\Databases\AdventureWorks> $db

WARNING: column "Owner" does not fit into the display and was removed.

Name                        Status          Recovery Model   CompatLvl        Collation
----                           ------          --------------           ---------            ---------
AdventureWorks       Normal          Simple                 100            SQL_Latin1_General_CP1_CI_AS


PS SQLSERVER:\SQL\OVERLORD\SQL2K8\Databases\AdventureWorks> $db.Script()

CREATE DATABASE [AdventureWorks] ON  PRIMARY
( NAME = N'AdventureWorks_Data', FILENAME = N'C:\data\MSSQL10.SQL2K8\MSSQL\DATA\AdventureWorks_Data.mdf' , SIZE = 174080KB , MAXSIZE = UNLIMITED, FILEGROWTH =16384KB )
 LOG ON
( NAME = N'AdventureWorks_Log', FILENAME = N'C:\data\MSSQL10.SQL2K8\MSSQL\DATA\AdventureWorks_Log.ldf' , SIZE = 18432KB , MAXSIZE = 2048GB , FILEGROWTH = 1638
4KB ) COLLATE SQL_Latin1_General_CP1_CI_AS
ALTER DATABASE [AdventureWorks] SET COMPATIBILITY_LEVEL = 100
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
    EXEC [AdventureWorks].[dbo].[sp_fulltext_database] @action = 'enable'
end
ALTER DATABASE [AdventureWorks] SET ANSI_NULL_DEFAULT OFF
ALTER DATABASE [AdventureWorks] SET ANSI_NULLS ON
ALTER DATABASE [AdventureWorks] SET ANSI_PADDING ON
.
.
.

 

The limitation we run with the above approach is that it doesn't include the objects such as tables, stored procedures, and functions in the script. That's why we have to write a loop to iterate all the tables, procedures, checks, primary, functions, etc. Each of those classes have the Script() method and we can invoke them as we need it. 

PS SQLSERVER:\SQL\OVERLORD\SQL2K8\Databases\AdventureWorks> for ($i=0; $i -lt $db.Tables.Count; $i++) {$db.Tables[$i].Script()}
.
.
.
 

Yes, there are more gotchas. :(

 

So far, we have looked into resolving this issue using 1 of the overloaded Script() method. The 2nd version of the overloaded method expects ScriptingOptions as one of the parameter. Here is how we would declare them and the options they give us.

PS SQLSERVER:\SQL\OVERLORD\SQL2K8\Databases\AdventureWorks> $sc = new-object("Microsoft.SqlServer.Management.Smo.ScriptingOptions")

Here is a quick list of properties we can set on the $sc (ScriptingOptions) object.


            $sc.AppendToFile = 0;
            $sc.Bindings = 1;
            $sc.Default = 1;
            $sc.DdlBodyOnly = 1;
            $sc.DriAll = 1;
            $sc.DriAllConstraints = 1;
            $sc.DriAllKeys = 1;
            $sc.DriPrimaryKey = 1;
            $sc.IncludeDatabaseContext = 1;
            $sc.IncludeDatabaseRoleMemberships = 1;
            $sc.IncludeHeaders = 1;
            $sc.IncludeIfNotExists = 1;
            $sc.Indexes = 1;
            $sc.LoginSid = 1;
            $sc.PrimaryObject = 1;
            $sc.Permissions = 1;

 

 Depending upon your need, you can set the target server version, and the output file properties as well.

Search for data on any given database and on any column

November 18
by Rajib Bahar 18. November 2009 15:47
In some of my previous project, I had to find out whether a particular data existed on anywhere in any database. By that I mean, if I wanted to find out whether a particular data, for example, "manager" made in to any table. It's a trivial issue if you know the database table structure and column names. What if you did not have that benefit and wanted to do a massive manhunt for the data? I have written similar script such as the one below, and forgot to keep track of it in my library. Finally, my slowly deteriorating and dull memory served as a motivation for this post. The way it works is a) by getting list of all available databases, b) using dynamic sql to capture tables and column information, c) comparing sought after data against any column that can be converted to varchar type. If you need more explanation then comment please. 
 
Here is the snippet:
 

SET NOCOUNT ON

 

DECLARE @SoughtAfterValue VARCHAR(8000)

 

SET @SoughtAfterValue ='Manager'

 

DECLARE @Tmp TABLE

(

      ID INT IDENTITY(1,1)

    , DBName VARCHAR(255)

)

 

INSERT INTO @Tmp(DBName)

SELECT name

FROM sys.sysdatabases

 

DECLARE @i INT

DECLARE @total INT

 

SET @i = 1

 

SELECT @total = COUNT(*)

FROM @Tmp

 

DECLARE @sql Nvarchar(max)

 

WHILE @i <= @total

BEGIN

 

            set @sql= N'

            use ' +(

                SELECTDBName FROM @Tmp WHEREID = @i

            ) + '

           

            DECLARE @TmpQry TABLE

            (

                    ID INT IDENTITY(1, 1)

                  , Qry VARCHAR(8000)

            )

           

       

        if exists

                  ( SELECT

                  *

        FROM INFORMATION_SCHEMA.COLUMNS

            WHERE TABLE_CATALOG = '''

        +

            (

                SELECTDBName FROM @Tmp WHEREID = @i

            )

        + '''

            )

            BEGIN

 

            INSERT INTO @TmpQry (Qry)

        SELECT

                  ''SELECT CAST('' +COLUMN_NAME + '' AS VARCHAR(8000))[Result] '' +

                ''FROM '

            +

            (

                SELECTDBName FROM @Tmp WHEREID = @i

            )

                  + '..' + ''' + TABLE_NAME  

                  + '' WHERE CAST('' +COLUMN_NAME + '' AS VARCHAR(8000)) like ''''%' +@SoughtAfterValue + '%''''''

                   

        FROM INFORMATION_SCHEMA.COLUMNS

            WHERE DATA_TYPE NOT IN

            (

                  ''binary'',''varbinary'', ''image'', ''geography'', ''geometry'', ''timestamp'',

                  ''xml'',''hierarchyid'', ''sql_variant''

            )

 

            END

 

            DECLARE @i INT

            DECLARE @Total INT

            DECLARE @CurrentQryVARCHAR(8000)

            DECLARE @CurrentQry2VARCHAR(8000)

           

            SET @i = 1

 

            SELECT @Total = COUNT(*) FROM@TmpQry

           

            WHILE @i <= @Total

            BEGIN

                 

                  SELECT @CurrentQry = Qry     

                  FROM @TmpQry WHERE ID =@i

           

                  SET @CurrentQry2 = ''ifexists('' + @CurrentQry +  '') begin select ''''''+ REPLACE(@CurrentQry,'''''''', '''''''''''') + '''''' [Query Ran] '' + @CurrentQry + '' end''

 

                  exec(@CurrentQry2)

 

                  SET @i = @i + 1

 

                  CONTINUE

            END

           

      '

 

exec(@sql)

 

      SET @i = @i + 1

      CONTINUE   

END

  

Trend

October 11
by Rajib Bahar 11. October 2009 10:37
It's a challenge to keep track of things as they are constantly changing (just like my tools of the trade). Don't you wish you are always on top of all things, but, other things in life get in the way... Some time I get immersed in work and study that I forget the rest of the world. 

Now, that I have this challenge at hand, the question is how am I going to pull myself through this one? I found a tool on it's face seemed quite interesting. My work involves working with SQL server. If I want to learn the noise around sql server then it will show what everyone in the world is thinking about it. I believe it utilizes the RSS feed from twitter. The people at codemunch.com wrote this very simple and useful tool (depending upon your value on it). I found their site while trying to find the trend on sql server. 

How to use it?

Here is what the URL for the trend on "SQL Server" would look like. 


Simply change the "q=" part to your preferred query. For example, you want find the latest on sql then the query string would look like "q=sql". If you want to use words with spaces in it then place a %20 between each word. It's as simple as that.

Other trends that I may use for myself include:

I am sure other Gurus may have different opionion how to find trend. After all, there are other reliable methods such as reading the book on latest tools, online articles, blogs, visiting focus groups that provide training in similar area. My intention with this entry is to talk about what other tool is out there to complement such effort. Anyways, I do find the existing methods useful from time to time. I have been to the local sql server user group many times. Most of the times, I went their for the swags, and free softwares. Most recently, I went to the "SQL Server Summit" hosted in minnesota with sponsorship from Digineer. I attended one of the reporting services session to learn about the challenges the MVP had in his project. Toward the end, I asked a question about SSRS and sharepoint and got good feedback from several peers. The presenter moved on to take other closing questions. In the meantime, I had this urge to tinker. I took out a yo-yo which I picked up from Digineer's booth prior to that presentation. I thought I'd play with it while the presentation ends. Unfortunatley, I did not know that the yo-yo's extra feature included very loud sound, and shiny lights. Yes, it was an awkwardly funny moment and all eyes were on me. I was in a panic mode trying to silence the alarm. Luckily for me, I did not get bounced out as I worked with some of the people in there running the show. I had an occassion to collaborate with Mark V. from digineer in the past. He was sitting next to me and cracked open. He did not know that the yo-yo would do that. I am making a note to avoid yo-yo's next time. BTW, I transferred the yo-yo to my nephew, but, I digress.

My YouTube VLOG

December 13
by Rajib Bahar 13. December 2008 22:16

I have 2 YouTube Video Log or VLOG.

One is work related and called the icsql channel. The clip below talks about SSIS script component changes:

My other VLOG is related to art and volunteer works I do around the community. I volunteer some of my free time to KFAI radio these days. Here is a radio interview I did with some notable friends like Matt Harding, Palbasha Siddiqui, and Garry Schyman:

 

Trying to claim my blog at Technocrati

December 05
by Rajib Bahar 5. December 2008 13:08
Technocrati requires a link back to them... Here is the link Technorati Profile.

SQL Data Auditor program

December 03
by Rajib Bahar 3. December 2008 06:27

My team and I have been working on building an enterprise tool to audit data in SQL Server. The 1st CTP permits you to remove redundant data. Other features will be available later. It is available for download at http://www.icdotnet.com.

Here is a screenshot: .

Some of my servers are down

December 01
by Rajib Bahar 1. December 2008 12:05

Sorry everyone...

 

The websites http://www.icdotnet.com and http://www.icsql.com is down today.

 

It will be up if all works out by tomorrow. 

Welcome

November 25
by Rajib Bahar 25. November 2008 10:42
Welcome to my blog site. Just restarting the blog...