One of the frequently asked questions in the newsgroups is how do you convert a string representation of a binary value to the equivalent binary value and the reverse.

The latter is often required to be able to print out the binary representation.

There have been a few undocumented functions and many home brew solutions.

In SQL Server 2008 CONVERT can now do it for you. Thanks to Itzik for pointing this out to me last night.

So you can now do the following

select convert(varchar(8), 0x023454, 1)

select convert(binary(3), '0x023454', 1)

Which is great.


This is cross posted from my SQLBlogcasts blog which can be found here, http://sqlblogcasts.com/blogs/simons/SQL Server 2008 - Converting binary(hex) values to strings

Categories:
SQL Server 2008


I really don't understand this. The ISDATE function doesn't work with new date and time types, whats more you can't pass it a string representing a date before 1/1/1753.

Try this

select ISDATE('1/1/1700')

in SQL 2008 it will return 0.

Whats odd is that there is no function to cater for these new dates.

So whats your option, well someone that attended the jumpstart training I did last month suggested using try catch. So here it is, a TSQL procedure to workout if a date is valid for the new types.

create procedure ISDATE2(@date varchar(20))

as

begin

    begin try

        declare @d date = @date

        return 1

    end try

    begin catch

        return 0

    end catch

end

go

declare @result bit

exec @result = dbo.isdate2 '1/1/1700'

select @result

Unfortunately you can't have begin try in a function.

The other option is to use a CLR function.


This is cross posted from my SQLBlogcasts blog which can be found here, http://sqlblogcasts.com/blogs/simons/SQL Server 2008 - ISDATE doesn't work with

Categories:
SQL Server 2008


Table Valued Parameters have to be one of the coolest features in SQL Server 2008. With them you are able to pass a set of data around as a single variable. What this means is that if you are saving multiple records you can do very easily in one procedure call.

You might say well I can do that already using an XML column or a delimited list, Well the difference with a Table Valued Parameter is that you get a typed rowset which you can use directly in an INSERT, SELECT, UPDATE statement, and anyother statement that can take a rowset. This means you don't have to shred your XML or have a function to split your delimited string.

create table myTable (col1 int, col2 datetime, col3 varchar(max))

go

create type myTableType as table (col1 int, col2 datetime, col3 varchar(max))

go

create procedure up_myTable_insertFromTable

  @myTableData myTableType readonly

as

  insert into myTable (col1, col2, col3 )

  select col1, col2, col3

    from @myTableData

go

declare @myTable myTableType

 

insert into @myTable values(1, getdate(), 'Table Valued Parameters are great')

 

exec up_myTable_insertFromTable @myTable

Its very easy to use.

There are a few gotchas to be aware of,

The stored procedure parameter has to be READONLY. This means that you cannot modify it within the stored procedure. You can only modify it in the scope it was created. i.e. If you created a table type variable in your procedure you can modify the data in it, however if you pass that to another procedure that other procedure cannot modify it as it wasn't create in the scope of that procedure.

A table valued parameter ALWAYS has a default of an empty table. This is not inline with all other types btu has been done for performance reasons. What this means is that in the previous code the following will work

exec up_myTable_insertFromTable

Even though you haven't passed in a value for the @myTableData parameter.

No statistics are created on a TVP. This is inline with table variables which means if you are doing selects with where clauses you have to be careful, as you may end up with table scans.

 


This is cross posted from my SQLBlogcasts blog which can be found here, http://sqlblogcasts.com/blogs/simons/SQL Server 2008 TSQL - Table Valued Parameters

Categories:
SQL Server 2008


Performing bulk inserts into a table when the table has an identity column has long bee a difficult challenge for client programming.

The difficulty has been getting the identity values that have been generated for the set of data you are saving. It becomes even more difficult when you want to save parent child relationships.

In SQL 2005 the OUTPUT clause was introduced which allowed you to return the identity values generated by a an insert of multiple rows (you can also generate any other data generated by the server i.e. defaults contrary to what BOL says). However there was one draw back. You couldn't relate the identity values to the original data set unless you had a natural key in your table or you stored a second surrogate key. This means you had to fully reload your client application data set. For large data sets thats not ideal.

This is because the OUTPUT clause for an INSERT statement can only reference the inserted pseudo table. This only contains the columns of the underlying table so you don't have access to any other data.

With SQL Server 2008 you get MERGE. MERGE is a combined INSERT, UPDATE and DELETE statement that supports the OUTPUT clause. I thought I would have a look and see if the same limitations apply to the OUTPUT claue as they do for the INSERT statement. Well they don't.

This means that you can return any value from your source data even if its not being inserted into the table. For example

CREATE TABLE Person (id int identity(1,1), name varchar(200))

 

MERGE INTO Person

USING (Values ('Simon',1),('Mark',2),('Stuart',3)) People(name,clientSideId)

ON 1=2

WHEN NOT MATCHED THEN

INSERT (name) values (People.Name)

OUTPUT People.clientSideId, Inserted.Id;

This allows you to update your client code with the idenity values generated by the server. Whilst this logically shold work, in CTP5 there is a bug that causes this to fail. It appears that the issue is to do with the ON clause. When the expression is always false something is causing a severe error. There are a number of workarounds, sometimes using a WHEN MATCHED clause will help and in others changing he USING to be a table reference and not a derived table helps.

For an example of saving parent child relationships have a look at the code below. This copies the objects and columns system views into new tables, whilst maintaining correct referential integrity.

The use of the @objectTab and @columnTab is to avoid the error mentioned above, once fixed this code can be greatly simplfied.

You might be thinking that this is goig to such from a performance stance. It doesn't. Whilst the execution plan costs is much higher than the straight insert the actual cost of cpu and IO can be less than the direct INSERT approach. I beleieve this is due to some sorting and assertions that are imposed in the MERGE statement which simplify the storage and upating of the underlying indexes.

Here is the code mentioned above. It returns two data sets that can be used to update your client data sets. You could combine into 1 data set if required.

drop table NewObject

go

drop table NewColumn

go

create table NewObject (id int identity(1,1) check (id > 0 ), name sysname)

go

create table NewColumn (id int identity(1,1), ObjectId int, name sysname)

go

set nocount on

 

declare @objects xml = (

select top 1000 object_id [@object_id]

      ,name [@name]

      ,(select column_id [@id], name [@name] from sys.columns where sys.columns.object_id = sys.objects.object_id for xml path('column'), Type )

from sys.objects

for xml path ('object'))

 

declare @NewObject table (new_id int, old_id int, unique ([old_id]))

declare @id int

declare @NewColumn table (new_id int, old_id int, new_col_id int, old_col_id int)

 

declare @objectTab table (name sysname, object_id int)

insert into @objectTab (name, object_id)

       select obj.node.value('@name','sysname') name

            , obj.node.value('@object_id','int') object_id

         from @objects.nodes('/object') obj(node)

 

merge into NewObject

using ( select name, object_id from @objectTab

       )src(name,id)

on NewObject.id = 0

when matched then

delete

when not matched then

insert (name) values(src.name)

output src.id, inserted.id into @NewObject (old_id, new_id);

 

select * from @NewObject

 

declare @columnTab table (name sysname,id int,  object_id int)

insert into @columnTab (name, id, object_id)

       select col.node.value('@name','sysname') name

            , col.node.value('@id','int') id

            , obj.node.value('@object_id','int') object_id

         from @objects.nodes('object') obj(node)

         cross apply obj.node.nodes('column') col(node)

 

merge into NewColumn

using (select col.name, col.object_id , col.id , obj.new_id new_object_id

        from @columnTab col

        join @NewObject obj on col.object_id = obj.old_id) col(name,old_object_id,old_col_id, new_object_id)

on 1=2

when not matched then

insert (name, ObjectId) values(col.name, col.new_object_id)

output col.old_object_id, col.old_col_id, col.new_object_id, inserted.id into @NewColumn (old_id, old_col_id, new_id, new_col_id);

 

select * from @NewColumn

 

 


This is cross posted from my SQLBlogcasts blog which can be found here, http://sqlblogcasts.com/blogs/simons/SQL Server 2008 - Batch inserts and identity columns using MERGE

Categories:
SQL Server 2008


If you are upgrading to Visual Studio 2008 then be careful with SQL Server.

You may or may not know that the Business Intelligence Development Studio (BIDS) is a visual studio shell. If you don't have Visual Studio installed when you install SQL Server then it installs a version of Visual Studio for you.

So how does this impact VS 2008. Well you may think that when you upgrade you can uninstall Visual Studio 2005.

STOP

You can uninstall VS 2005, but make sure you don't uninstall the shell used by SQL for BIDS. How do you know what that is? I'll tell you its "VS 2005 Premier Partner Edition".

If you uninstall this you will not be able to use BIDS, so you won't be able to develop Integration services packages, Reporting Services reports, or Analysis Services Database. Whats more based on my experience you have to jump through a few hoops to get BIDS installed again.

You might think why can't I use VS2008, well the simple answer is that Microsoft haven't developed the project types ( the designers etc that work in VS for SSIS, SSRS and SSAS) for VS2008.

VS2008 will be used for the Katmai version of BIDS so if you have to support a SQL2005 and a SQL 2008 instance you will need to make sure you keep your SQL2005 BIDS lying around. Unfortunately the benefit of VS2008 replacing VS2005 by supporting all .Net versions ( 2.0, 3.0 and 3.5) is not the same for us SQL guys we have to stick with both versions.

 


This is cross posted from my SQLBlogcasts blog which can be found here, http://sqlblogcasts.com/blogs/simons/Installing Visual Studio 2008 and SQL Server 2005

Categories:
SQL Server 2008


Katmai increases the concurrency of SSIS packages by a change to the pipeline.

In SQL 2005 a dataflow is split into sections, This is called the execution tree. Each section has the same buffer strucuture and the buffers are passed to each component in the section of the pipeline. A new secton starts when an asynchronous component is found. i..e the buffer in is not the buffer out like the aggregation component

The key here is that the data is not copied to a new buffer for each component. Rather each component accesses the same buffer (one after each other). This is great because copying data is an expensive operation.

However it does mean that you are limited to one active buffer. So if you have multiple components only one is accessing the buffer at anyone time.

Well that was the case in SQL 2005. In SQL 2008 the situation changes. Each component will be able to access a buffer thus greatly increasing the ability for you package to run quicker. You are still restrcited by the resources on your machine, CPU and memory being the main ones for SSIS.

I was reading Alberto Ferrari's blog and though of this http://sqlblog.com/blogs/alberto_ferrari/archive/2007/11/15/ssis-multicast-and-trash-or-separate-and-union.aspx. In Albertos situation he initially uses multicast and conditional split. Whilst you might think these cause new sections in the execution tree, they don't they are in fact synchronous components. What this means is that in the first package he is only maintaining one copy of the data.

However in the second the use of the UNION which is an asynchrone ous component, a new section is started and thus the data is copied into a new buffer and so the time difference he experiences is due to the fact that the data is being copied.

In summary once data is in the SSIS section of a pipeline if you use it or not is irrelevant. If a piece of data is not used at all, then don't put it in the pipeline. Thats why you get the warning message saying a column is't being used. Your package may perform better if it is not used.

So bring on Katmai and we should see Albertos scenario improve even further.


This is cross posted from my SQLBlogcasts blog which can be found here, http://sqlblogcasts.com/blogs/simons/SSIS Pipeline - Katmai changes - Reusing data

Categories:
SQL Server 2008


I read Steve Jones editorial inDatabase Weekly today and saw his statement.

"I still recommend jumping from 2000 to 2008 if you haven't already upgraded"

My personal view is that if you are looking to replace your systems then 2005 has some great features that you get out of the box and is now stable.

Some of the most important features for me are around consistency and recoverability. I've had 2 clients in as many weeks that have supsect databases. Something has caused data corruptions and the database is inaccessible.

SQL 2005 has page checksums which are a great mechanism to prevent crap from being written or read from the disk. It is also contains numerous bug fixes that SQL 2000 doesn't.

But this on top of the fact that SQL 2008 (Katmai) will not RTM for a considerable amount of time and the first service pack probably won't be in during 2008 (but what do I know). That means to get a stable SQL 2008 you have to wait at least 14 months.

Further more having native 64bit versions of SQL means that the scalability of SQL 2005 is so much more that SQL 2000 especially on standard edition.

Personally I would move to SQL 2005 now, to benefit from the high availability and scalability features.


This is cross posted from my SQLBlogcasts blog which can be found here, http://sqlblogcasts.com/blogs/simons/Should you wait for Katmai.

So you get a new CTP. How do you find out whats changed?

Well the first port of call should be BOL. We are told that for Katmai, BOL content will ship with the feature, which is good to know.

But what if you don't have BOL or you don't trust it. Well the system resource database contains most features. So have a look at that.

I recently did this for a build of Katmai without BOL and was able to find system procedures, functions and dmvs that were new.

I'm going to start a DataDude project on the resource database that way I can easily track changes between releases.

So how do I look at the resource database. The easiest way is to copy the mdf and ldf files in your data folder and then attach the database as another name.


This is cross posted from my SQLBlogcasts blog which can be found here, http://sqlblogcasts.com/blogs/simons/Whats new in Katmai?

Categories:
SQL Server 2008

Theme design by Nukeation based on Jelle Druyts