Login or Sign Up to become a member!

EXPERTS, INFORMATION, IDEAS & KNOWLEDGE

Social bookmarker Add this

Your profile

Search

July 2009
Mon Tue Wed Thu Fri Sat Sun
 << <   > >>
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

XML Feeds

Authors

The Data Management Journal

Automatically create a SQL Server table in a new database.

by George Mastros


Permalink 03 Jul 2009 10:53 , Categories: Data Modelling & Design, Microsoft SQL Server Admin, Microsoft SQL Server

I've seen this question numerous times in the forums I like to frequent. The idea is, when you create a new database, you may want that database to have several tables, some of which are automatically populated with data (thinking about relatively static lookup tables here).

The process mentioned here may not be useful for everyone, but it is certainly something to consider.

There is a system database named Model. This database is used when you create a new user database. In fact, any object (table, view, stored procedures, functions, etc…) that exists in the model database will be copied to your newly created database. This may be a blessing and a curse, so use this suggestion wisely. If you have a SQL Instance where you need to set up a new database for each customer, and that is all the instance is used for, then it makes sense to create your objects in the Model database. However, if you have a general purpose instance that you are using for various databases, you probably won’t want to put your objects in the Model database.

Enough of the chatter, let's see how this can be done.

First, create a table in the Model database.

  1. USE Model
  2. go
  3.  
  4. CREATE TABLE TestAutoDBCreation(Id INT, Color VARCHAR(20))
  5. INSERT INTO TestAutoDBCreation VALUES(1, 'Red')
  6. INSERT INTO TestAutoDBCreation VALUES(2, 'Blue')

Now, let’s create a new database.

  1. USE Master
  2. go
  3. CREATE DATABASE NewDatabaseWithModelTable

Now, let's make sure the table (and it's data) exist in the new database.

  1. USE NewDatabaseWithModelTable
  2. go
  3. SELECT * FROM TestAutoDBCreation

As you can see, the table that was created in Model exists in the newly created database. It even has all the data that was loaded in to it.

Now, let’s clean up after ourselves:

  1. USE Model
  2. go
  3. DROP TABLE TestAutoDBCreation
  4. go
  5. USE Master
  6. go
  7. DROP DATABASE NewDatabaseWithModelTable
2 comments »Send a trackback » 178 views

Dynamic column names and fields in SSRS (Custom Matrix)

by onpnt


Permalink 01 Jul 2009 12:26 , Categories: Data Modelling & Design, Database Programming, Database Administration, Microsoft SQL Server Admin, Microsoft SQL Server

I had no choice but to do work with creating dynamic column headings and dynamically determine what field in my dataset should go where in a report today. Sense this is the second time I’ve gone through this exercise and knowing the lack of information out there on really how to do it, I thought it deserves a blog entry.

So here is the basis of the requirements. You have a query that uses PIVOT but thrown into the mix is the need for dynamic columns in the PIVOT. This is usually a task when you are going after things like current week plus the last 52 weeks. That was the case in this situation. I needed to bring in a dynamic set of columns to be used in PIVOT. The matrix in 2005 did not give me what I needed in the end result so this is the path I took.

First task is to write the procedure to use PIVOT with dynamic column headers. I’m not going to go into that method sense it’s well documented out there and out of scope. I will point you to Pivots with Dynamic Columns in SQL Server 2005 as it explains the way to accomplish this well.

I wrote something in AdventureWorks to for this example so if you have AdventureWorks floating around you should be able to read this and run through step for step with success.

Here is our procedure. I’m sure my methods will take great notice from my local TSQL friends :) The dynamic SQL more so than anything...

  1. CREATE PROCEDURE GetSalesPerWeek
  2. AS
  3. DECLARE @weeks_ordered TABLE (num VARCHAR(3))
  4. DECLARE @weeks TABLE (wk INT)
  5. DECLARE @DATE DATETIME
  6. DECLARE @cols NVARCHAR(3000)
  7. DECLARE @INT INT
  8. DECLARE @col_pv VARCHAR(2000)
  9. DECLARE @query VARCHAR(3000)
  10.  
  11.  
  12. SET @INT = 1
  13. SET @DATE = GETDATE()
  14.  
  15. WHILE @INT <= 52
  16. BEGIN
  17.     INSERT INTO @weeks VALUES (@INT)
  18.     SET @INT = @INT + 1
  19. END
  20.  
  21.  
  22. INSERT INTO @weeks_ordered
  23. SELECT
  24. wk
  25. FROM @weeks
  26. ORDER BY
  27. CASE WHEN DATEPART(wk,@DATE) - wk < 0
  28. THEN DATEPART(wk,@DATE) - wk + 53
  29. ELSE DATEPART(wk,@DATE) - wk
  30. END DESC
  31.  
  32. SELECT @col_pv = STUFF(( SELECT  
  33.                                 '],[' + w.num
  34.                         FROM  @weeks_ordered AS w
  35.                         FOR XML PATH('')
  36.                       ), 1, 2, '') + ']'
  37.  
  38. SELECT  @cols = STUFF(( SELECT  
  39.                                 '],0) as W' + CASE WHEN CAST(w.num - 1 AS VARCHAR(2)) = 0 THEN '52' ELSE
  40.                                                         CAST(w.num - 1 AS VARCHAR(2)) END + ',isnull([' + w.num
  41.                         FROM  @weeks_ordered AS w
  42.                         FOR XML PATH('')
  43.                       ), 1, 2, '') + '],0) as W' + CAST(DATEPART(wk,GETDATE()) AS VARCHAR(2))
  44.  
  45.  
  46. IF OBJECT_ID('tempdb.dbo.#detail') IS not null
  47.         DROP TABLE #detail
  48.  
  49. CREATE TABLE #detail
  50. (
  51. AccountNumber VARCHAR(10)
  52. ,PruductNumber VARCHAR(25)
  53. ,OrderQty INT
  54. ,WeekNumber SMALLINT
  55. )
  56.  
  57.  
  58. INSERT INTO #detail
  59. SELECT
  60.     cust.AccountNumber
  61.     ,items.ProductNumber
  62.     ,det.OrderQty
  63.     ,DATEPART(wk,hdr.ShipDate) WeekNumber
  64. FROM
  65. Sales.SalesOrderHeader hdr
  66. INNER Join Sales.SalesOrderDetail det ON hdr.SalesOrderID = det.SalesOrderID
  67. INNER Join Production.Product items ON det.ProductID = items.ProductID
  68. INNER Join Sales.Customer cust ON hdr.CustomerID = cust.CustomerID
  69. INNER Join @weeks ord ON DATEPART(wk,ShipDate) = wk
  70. WHERE ShipDate >= DATEADD(wk,-52,'2004-06-01')
  71. GROUP BY
  72.     cust.AccountNumber
  73.     ,items.ProductNumber
  74.     ,det.OrderQty
  75.     ,DATEPART(wk,hdr.ShipDate)
  76.     ,wk
  77. ORDER BY
  78. CASE WHEN DATEPART(wk,ShipDate) - wk < 0
  79. THEN DATEPART(wk,ShipDate) - wk + 53
  80. ELSE DATEPART(wk,ShipDate) - wk
  81. END
  82.  
  83.  
  84. SET @query =
  85. '
  86. Select 
  87.     AccountNumber
  88.     ,PruductNumber
  89.     , '     + RIGHT(@cols,LEN(@cols)-10) + '
  90. From
  91.     #detail as sales
  92. PIVOT (sum(OrderQty) FOR WeekNumber IN (' + @col_pv + ')) as pv
  93. Order By AccountNumber
  94. '
  95. EXEC(@query)


The results shows us the PIVOT results of each account number and the sales for the week of the year

The problem with all of this is the dynamic nature of the column names. In reporting services we’re used to handling column names as static entities. So here is how we’ll build our report given the fact these column names can and will change over time.

So create a new report in your solution and add a new DataSet. Make it a text call with the following statement

  1. EXEC GetSalesPerWeek

Run the DataSet to verify everything comes in ok.

Now add a new table to your empty report. Add the account number and product number as you would normally. Next we need to figure out what week is actually first. To do this we’re going to write a function in the code section of SSRS

In the layout tab go to Report and select Report Properties. This will give you the properties for the entire report. Select the Code tab. Copy and paste the following code into the window

  1. Public Function GetColumnHeading(ByVal x As Integer)
  2.        Dim WeeksArr As New System.Collections.ArrayList()
  3.         Dim i As Long
  4.         Dim CurrentWeek As Long
  5.  
  6.         CurrentWeek = DatePart(DateInterval.WeekOfYear, System.DateTime.Now)
  7.  
  8.         For i = 1 To 52
  9.             WeeksArr.Add(1 + (i + CurrentWeek - 1) Mod 52)
  10.         Next
  11.         Return WeeksArr(x)
  12.     End Function

This code was written by our own gmmastros. Thanks to him for this and the help it gave me when I needed it. Gets the job done and it does it quickly.

Final results should look like this

Hit OK to save.

Now in the field next to the Product Number go ahead and enter an expression for the heading like this

="W" & Code.GetColumnHeading(0)

Recall in our procedure we return each week as Wnn for the week number. So in our code we created an ArrayList filled up with the order we want. The same order we based the procedure off of. Now by using the index of the ArrayList we can simply call for the heading that should be all the way to the left (-51 weeks from the current) by means of index of 0. In the details textbox we can then simply do the following as well given the same guidelines

=Fields("W" & Code.GetColumnHeading(0)).Value

Most developers don’t know they can reference the fields by name in this manner. Usually it just isn’t required and that is the case. It can be useful to note that you can dynamically fill the object name in though and get the same results as Fields!name.Value

I went ahead and put a few more columns and increased the index requested from the ArrayList. Running that results in the following.

Now you have your customer matrix in a sense by means of dynamic column and field referencing. You also a nice example of PIVOT by means of dynamic column names.

This blog probably has about 12 pages worth of explanations but I’d like to leave those to the forums so please follow the directions below if you want to discuss this method further. Otherwise, have fun with it!




*** If you have a SQL related question try our Microsoft SQL Server Programming forum or our Microsoft SQL Server Admin forum

3 comments »Send a trackback » 353 views

How To Script Out The Whole Database In SQL Server 2005 and SQL Server 2008

by SQLDenis


Permalink 01 Jul 2009 09:36 , Categories: Data Modelling & Design Tags: how to, scripting, sql server 2005, sql server 2008

There seems to be a little bit of confusion on how to script out the database. The correct answer is of course: just run all the scripts you have in source control :-)

So for those who do not use/have source control I will show you how to do it

Logically you would think that this would be the way: Right click on the database --> Script Database As --> CREATE To and then pick your choice. See also image below


Script database

What that will do is just create the database and not much else, here is what the script might look like

  1. USE [master]
  2. GO
  3.  
  4. /****** Object:  Database [AdventureWorks]    Script Date: 06/30/2009 15:04:19 ******/
  5. CREATE DATABASE [AdventureWorks] ON  PRIMARY
  6. ( NAME = N'AdventureWorks_Data', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\AdventureWorks_Data.mdf' , SIZE = 174080KB , MAXSIZE = UNLIMITED, FILEGROWTH = 16384KB )
  7.  LOG ON
  8. ( NAME = N'AdventureWorks_Log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\AdventureWorks_Log.ldf' , SIZE = 2048KB , MAXSIZE = 2048GB , FILEGROWTH = 16384KB )
  9. GO
  10.  
  11. ALTER DATABASE [AdventureWorks] SET COMPATIBILITY_LEVEL = 100
  12. GO
  13.  
  14. IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
  15. BEGIN
  16. EXEC [AdventureWorks].[dbo].[SP_FULLTEXT_DATABASE] @ACTION = 'enable'
  17. END
  18. GO

What you have to do is actually this: Right click on your database-->Tasks-->Generate Scripts


Script Wizard

Select the database you want to script and make sure you check the option at the bottom that says Script all objects in the selected database. See image below


Script all objects in the selected database

That is all, click next a couple of times and review your options and you are set




*** If you have a SQL related question try our Microsoft SQL Server Programming forum or our Microsoft SQL Server Admin forum

3 comments »Send a trackback » 120 views

Adding time offsets passed in to a datetime to generate localized datetime

by SQLDenis


Permalink 26 Jun 2009 12:44 , Categories: Data Modelling & Design Tags: dates, datetime, parsing, time, utc time

I answered this question today and thought it would be useful to create a little post

If you have a varchar value like this '2009-06-26 14:30:00.000Z+4:30' you want to take 4 hours and 30 minutes and then subtract that from the date itself so in this case you will get 2009-06-26 11:00:00.000. The reason you subtract is because the +4:30 means that this was generated in a zone that is 4:30 ahead of utc

So first we need to figure out a couple of things
1) where are the minutes?
2) where is the hour?
3) is it positive or negative?

Here are the answers
1) where are the minutes?
The minutes are the last 2 characters

  1. DECLARE @DATE VARCHAR(100)
  2. SELECT @DATE = '2009-06-26 14:30:00.000Z+4:30'
  3.  
  4. SELECT RIGHT(@DATE,2)

2) where is the hour?
The hour starts after the Z and last for 2 or 3 characters including the sign, we will just grab 3 and replace : with an empty string

  1. DECLARE @DATE VARCHAR(100)
  2. SELECT @DATE = '2009-06-26 14:30:00.000Z+4:30'
  3. SELECT REPLACE(SUBSTRING(@DATE,PATINDEX('%z%',@DATE)+ 1,3),':','')
  4. go

+4


  1. DECLARE @DATE VARCHAR(100)
  2. SELECT @DATE = '2009-06-26 14:30:00.000Z-4:30'
  3. SELECT REPLACE(SUBSTRING(@DATE,PATINDEX('%z%',@DATE)+ 1,3),':','')
  4. go

-4


  1. DECLARE @DATE VARCHAR(100)
  2. SELECT @DATE = '2009-06-26 14:30:00.000Z+14:30'
  3. SELECT REPLACE(SUBSTRING(@DATE,PATINDEX('%z%',@DATE)+ 1,3),':','')

+14

3) is it positive or negative?
That we already grabbed above for the hour, for the minute we need to do something like this

  1. DECLARE @DATE VARCHAR(100),@multiplier INT
  2.  
  3. SELECT @DATE = '2009-06-26 14:30:00.000Z+4:30'
  4. SELECT  CASE WHEN @DATE like '%+%' THEN -1 ELSE 1 END

We also need to convert the stuff we did above to integers in order to add

So here is the complete code

  1. \
  2. DECLARE @DATE VARCHAR(100),@multiplier INT
  3.  
  4. SELECT @DATE = '2009-06-26 14:30:00.000Z+4:30'
  5. SELECT @multiplier = CASE WHEN @DATE like '%+%' THEN -1 ELSE 1 END
  6.  
  7.  
  8. SELECT DATEADD(mi, @multiplier *CONVERT(INT,RIGHT(@DATE,2)),DATEADD(hh
  9.     ,-1 * CONVERT(INT,REPLACE(SUBSTRING(@DATE,PATINDEX('%z%',@DATE)+ 1,3),':',''))
  10.     ,LEFT(@DATE,23)))
  11. go
  12.  
  13.  
  14. --2009-06-26 10:00:00.000
  15.  
  16. DECLARE @DATE VARCHAR(100),@multiplier INT
  17.  
  18. SELECT @DATE = '2009-06-26 14:30:00.000Z-4:30'
  19. SELECT @multiplier = CASE WHEN @DATE like '%+%' THEN -1 ELSE 1 END
  20.  
  21. SELECT DATEADD(mi, @multiplier *CONVERT(INT,RIGHT(@DATE,2)),DATEADD(hh
  22.     ,-1 * CONVERT(INT,REPLACE(SUBSTRING(@DATE,PATINDEX('%z%',@DATE)+ 1,3),':',''))
  23.     ,LEFT(@DATE,23)))
  24. go
  25.  
  26. --2009-06-26 19:00:00.000
  27.  
  28. DECLARE @DATE VARCHAR(100),@multiplier INT
  29.  
  30. SELECT @DATE = '2009-06-26 14:30:00.000Z+14:30'
  31. SELECT @multiplier = CASE WHEN @DATE like '%+%' THEN -1 ELSE 1 END
  32.  
  33. SELECT DATEADD(mi, @multiplier *CONVERT(INT,RIGHT(@DATE,2)),DATEADD(hh
  34.     ,-1 * CONVERT(INT,REPLACE(SUBSTRING(@DATE,PATINDEX('%z%',@DATE)+ 1,3),':',''))
  35.     ,LEFT(@DATE,23)))
  36. go
  37.  
  38. --2009-06-26 01:00:00.000
  39.  
  40.  
  41. DECLARE @DATE VARCHAR(100),@multiplier INT
  42. SELECT @DATE = '2009-06-26 14:30:00.000Z-14:30'
  43. SELECT @multiplier = CASE WHEN @DATE like '%+%' THEN -1 ELSE 1 END
  44.  
  45. SELECT DATEADD(mi, @multiplier *CONVERT(INT,RIGHT(@DATE,2)),DATEADD(hh
  46.     ,-1 * CONVERT(INT,REPLACE(SUBSTRING(@DATE,PATINDEX('%z%',@DATE)+ 1,3),':',''))
  47.     ,LEFT(@DATE,23)))
  48. go
  49.  
  50. --2009-06-27 05:00:00.000




*** If you have a SQL related question try our Microsoft SQL Server Programming forum or our Microsoft SQL Server Admin forum

2 comments »Send a trackback » 1014 views

Can't depend on sp_depends? Try using sp_refreshsqlmodule

by SQLDenis


Permalink 26 Jun 2009 10:17 , Categories: Data Modelling & Design Tags: howto, sql server 2008, trick

This will not work on SQL Server 2000 since the sp_refreshsqlmodule does not exists on that version!

A while back in the What is deferred name resolution and why do you need to care? blogpost I showed you that sp_depens is not reliable because you can create procedures that reference objects that have not been created yet.

You can use sp_refreshsqlmodule to help 'fix' that
let's take a look at how that works

First create this awesome stored procedure

  1. CREATE PROCEDURE prBla
  2. AS
  3. SELECT * FROM Blah
  4. go

Now execute sp_depends

  1. EXEC SP_DEPENDS 'Blah'

Server: Msg 15009, Level 16, State 1, Procedure sp_depends, Line 25
The object 'Blah' does not exist in database 'tempdb' or is invalid for this operation.

So that tells us that the table Blah does not exist. Fine, what happens if we run sp_depends for the proc?

  1. EXEC SP_DEPENDS 'prBla'

Object does not reference any object, and no objects reference it.

That makes sense since the table does not exist. Let's create this table

  1. CREATE TABLE Blah
  2. (SomeCol INT)

Now run sp_depends again for the table and the project

  1. EXEC SP_DEPENDS 'Blah'

Object does not reference any object, and no objects reference it.

  1. EXEC SP_DEPENDS 'prBla'

Object does not reference any object, and no objects reference it.



Okay so SQL server knows that the table Blah has been created but it still does not know that it is beeing used in the proc

Will executing the proc change that perhaps?

  1. EXEC  prBla
  1. EXEC SP_DEPENDS 'Blah'

Object does not reference any object, and no objects reference it.

  1. EXEC SP_DEPENDS 'prBla'

Object does not reference any object, and no objects reference it.

Nope, no such luck, that didn't do anything
Now execute the sp_refreshsqlmodule proc

  1. EXEC sp_refreshsqlmodule 'prBla'

Execute sp_depends again

  1. EXEC SP_DEPENDS 'Blah'

In the current database, the specified object is referenced by the following:

name		type
dbo.prBla	stored procedure

Yep, now it is showing us that table Blah is used by the stored proc prBla
Will it work when we run sp_depends for the stored procedure?

  1. EXEC SP_DEPENDS 'prBla'

In the current database, the specified object references the following:

name		type		updated	selected	column
dbo.Blah	user table	no	yes		SomeCol

And as you can see it also shows that the table is used..like Borat would say "Very Nice"

Clean up by dropping these sample objects

  1. DROP TABLE Blah
  2. go
  3. DROP PROCEDURE prBla
  4. go




*** If you have a SQL related question try our Microsoft SQL Server Programming forum or our Microsoft SQL Server Admin forum

Leave a comment »Send a trackback » 174 views

:: Next >>