Feeds:
Posts
Comments

Archive for the ‘Solutions’ Category

I am writing this article in response to one of my junior database developer’s questions, how to insert Arabic data in SQL table, as he had inserted few Arabic names in the table. However, once he selected the data after insertion he found ????? instead of Arabic text in the field. This is a general problem with developers when they work for multi lingual (other than English) environment.

Lets generate this issue step by step.
Step 1 :
First create a table to demonstrate it.

Create table test
(
[Employee ID] int identity(1,1),
[Employee Name] varchar(50)
)

Step 2 :
Insert Arabic text (any non-English text) into the table.

Insert into test ([Employee Name]) values('عمران')

Step 3 :
Browse the data from table.

Select * from test
--OUTPUT

insertarabictext1.1
Oooops, it became garbage (?????) 

Resolution :
Lets resolve it step by step.

Step 1 :
As you can see, the [Employee Name] (Column) has a data type of varchar, so you need to change it to nvarchar data type. Given below is the script to change it.

Alter table dbo.test Alter column [Employee Name] nvarchar(50)

Step 2 :
Insert the same record again with additional N before name.

Insert into test ([Employee Name]) values(N'عمران')
--OUTPUT

insertarabictext1.2

Step 3 :
Browse the data from table.

Select * from test
--OUTPUT

insertarabictext1.3

Conclusion :
Whenever you insert any language (other than English) text into SQL table you must check two things :

  • Data type of the field must be nvarchar.
  • Insert N before the text.

Read Full Post »

In my earlier article, I wrote about different aspect of Concat function introduced in SQL Server 2012. In this article, we will compare the Concat function with the traditional concatenation techniques and analyze the performance.

Method 1 : Using ISNULL With + (String Concatenation)

Use AdventureWorks2012
GO
Select
ISNULL([firstName],'')
+ ' '
+ ISNULL([MiddleName],'')
+ ' '
+ ISNULL([LastName],'') from [HumanResources].[vEmployee]

Method 2 : Using COALESCE With + (String Concatenation)

Use AdventureWorks2012
GO
Select
COALESCE([firstName],'')
+ ' '
+ COALESCE([MiddleName],'')
+ ' '
+ COALESCE([LastName],'')
from [HumanResources].[vEmployee]

Method 3 : Using Concat function of SQL Server 2012

Use AdventureWorks2012
GO

Select
CONCAT (
[firstName]
, ' '
, [MiddleName]
, ' '
, [LastName]) from [HumanResources].[vEmployee]

All of the above methods will give you the same result sets but lets view their performance given below.

Method

Concatenation expression

CPU Time

Elapsed Time

1

ISNULL([firstName],”) + ‘ ‘+ ISNULL([MiddleName],”) + ‘ ‘ + ISNULL([LastName],”)

141 ms

2234 ms

2

COALESCE([firstName],”) + ‘ ‘ + COALESCE([MiddleName],”)  + ‘ ‘ + COALESCE([LastName],”)

187 ms

3185 ms

3

CONCAT( [firstName], ‘ ‘, [MiddleName], ‘ ‘, [LastName])

94 ms

1821 ms

Conclusion :
It is needless to stress that Concat function is much faster than the other methods.

Note : The above queries have been tested on ~100K records.

Read Full Post »

I have been using Database email for a long time. This is very nice features introduced in SQL Server 2005. But when it comes to HTML formatting, you need to know a little bit HTML to format it and it takes a quite a while to format it. In this article, I will share a tip that can make your life easy and you can format even a complex HTML formatted email in few minutes.

Lets process it step by step.

Step 1 :
Mostly we receive the email format in word documents. First of all, you need to open the word document in MS word.
Sample attached Test Document 1.1.
SQL email1.1

Step 2 :
Then Go to File menu>>Save as and save it as html document.
SQL email1.2

Step 3 :
Open the saved html document, right click on it and go to view source.
SQL email1.3

Step 4 :
It will open a new window. Now you need to search for the tags namely Body and /Body and whatever text lies between both tags, just copy and paste it in the SQL query window.
SQL email1.4

Step 5 :
Now, you need to replace one single quote (‘) to two single quotes (”) in SQL query window and add single quote (‘) in the beginning and end of the text. Rest of the format will remain same.

Use msdb
GO
EXEC sp_send_dbmail @profile_name='My profile',
@recipients='mimran18@gmail.com',
@subject='Test Message with Formatted HTML',
@body_format = 'HTML' ,
@body='</pre>
<div class="WordSection1"><s>This is a TEST email</s>

<i><span style="text-decoration: underline;">This
is a TEST email</span></i>

This is a TEST email

This is a TEST
<table class="MsoTableLightListAccent1" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="97"><span class="SpellE"><b>S.No</b></span><b></b></td>
<td valign="top" width="375"><b>SQL Server Versions</b></td>
</tr>
<tr>
<td valign="top" width="97"><b>1</b></td>
<td valign="top" width="375">SQL Server 2005</td>
</tr>
<tr>
<td valign="top" width="97"><b>2</b></td>
<td valign="top" width="375">SQL Server 2008</td>
</tr>
<tr>
<td valign="top" width="97"><b>3</b></td>
<td valign="top" width="375">SQL Server 2012</td>
</tr>
</tbody>
</table>
</div>
<pre>
'

Step 6 :
Now, just execute it and it will send a nice formatted HTML email.

Read Full Post »

In this article,  we will discuss how to convert user defined objects to system objects and the reason to convert. Sometimes you develop general database procedures and functions that help you perform your daily operation quickly. But the issue is you need to create all these procedures and functions in the databases and after finishing the task you need to remove it also. A few days ago during my research I found a solution and with the help of this solution you don’t need to create / remove the script again and again in all databases. The solution is an undocumented stored procedure namely sp_ms_marksystemobject . But how it works, lets discuss stepwise.

Step 1 :
Given below is the script that can give you the column name (along with comma and brackets [ ]) of any table in a particular database and later on you can use it to insert, update or select statements.

Use AdventureWorks2012
GO
Create Procedure SP_ColumnNames
@object_name nvarchar(Max)
as
Select (Case when [column_id] = 1 then ' ' else ',' end)
+ QuoteName([name]) As [Column Name]
from sys.columns
where object_id=Object_id(@Object_name)
GO

Step 2 :
Now, you need to use the same database to execute the above stored procedure.

Use AdventureWorks2012
Go
SP_ColumnNames 'Sales'

systemobjects1.1

Step 3 :
If you try to use the same procedure in another database it will not work until unless you create the same procedure there. Lets see.

Use test
GO
SP_ColumnNames 'Student'

systemobjects1.2

If you look at the above error, it says you must deploy the above stored procedure in all databases wherever you need to use it. But this is a common tool and I need to deploy it once and need to use it in all the databases at the server. The solution is available in Step 4.

Step 4 :
Simply create your user defined stored procedure in master database and convert it to system stored procedure using sp_ms_marksystemobject.

Use master
GO
Create Procedure SP_ColumnNames
@object_name nvarchar(Max)
as
Select (Case when [column_id] = 1 then ' ' else ',' end)
+ QuoteName([name]) As [Column Name]
from sys.columns
where object_id=Object_id(@Object_name)
GO
sp_ms_marksystemobject  'SP_ColumnNames'

Step 5 :
Now, you can use this stored procedure in any database in the same server without creating it in all databases.
Lets try.

Use AdventureWorks2012
Go
SP_ColumnNames 'dbo.sales'
GO
Use test
Go
SP_ColumnNames 'Student'

sytemobject1.4

Conclusion :
You can deploy your general stored procedure and function once in the master database to perform daily operations and as many times as you can use it, in as many as databases you wish, without creating the stored procedure and functions time and again.

Note : This solution is not recommended for live database servers, you can use it in the development and testing server to expedite your development and testing.

Read Full Post »

sys.sysprocesses is one of the helpful system views when it comes to query the processes of SQL Server. I have been using this system view for quite a while. But a few days ago I read on MSDN, “This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently uses this feature.”

So, I planned to upgrade my query.
Given below is my query that I used to retrieve processes using specified database since SQL Server 2000.

--This query will work fine on SQL Server 2000 and above.
Declare @database_name as varchar(max)
Set @database_name ='AdventureWorks2012'

Select [spid] as [session_id], [last_batch],[status]
,cmd as [Command], hostname as [host_name]
,[program_name], [loginame] as [Login_name]
from sys.sysprocesses
Where dbid = db_id(@database_name)

sysprocesses1.1

Given below is my new query that works on SQL Server 2012 and above, having the same result set as the above.

Declare @database_name as varchar(max)
Set @database_name ='AdventureWorks2012'

Select A.session_id,A.last_request_end_time as [last_batch],A.[status]
, B.[command],A.[host_name]
,A.[program_name],A.[login_name]
from sys.dm_exec_sessions A
Left Join sys.dm_exec_requests B
On A.[session_id]=B.[session_id]
Where A.[database_id]=db_id(@database_name)

sysprocesses1.2

Conclusion :
You can see that both the above queries result set is same but first query (sys.sysprocesses) will not be applicable for future versions of SQL.

Let me know your feedback regarding both queries.

Read Full Post »

sp_spaceused is one of the frequently used stored procedures when it comes to view the number of rows, reserved size, data size, index size, unused space in a table. I myself utilized it many a time.

Given below are the three methods to run sp_spaceused or equivalent for all tables in a database to get number of rows, reserved size, data size, index size, unused space but this time we will measure the performance as well.

Method 1 :
Given below is one line script that can achieve the required result but it will cost you a performance issue because it will loop all the tables in the database one by one and will give you the result set.

EXECUTE sp_MSforeachtable 'EXECUTE sp_spaceused [?]';

Given below is one of the server execution times.
SQL Server Execution Times:
CPU time = 203 ms, elapsed time = 1768 ms.

If you have more tables, it will give you the error message as given below.
The query has exceeded the maximum number of result sets that can be displayed in the results grid. Only the first 100 result sets are displayed in the grid.

Method 2 :
Given below is another method to achieve it but this method will also cost you a performance issue because it will also loop all the tables in the database one by one and will give you the result set. Reference

Set statistics time on
CREATE TABLE ##TempTable
(name nvarchar(128)
,rows char(11)
,reserved varchar(18)
,data varchar(18)
,index_size varchar(18)
,unused varchar(18)
)
declare @UserTableName nvarchar(40)
declare UserTableSize cursor for
select rtrim(name) from dbo.sysobjects
where OBJECTPROPERTY(id, N'IsUserTable') = 1 order by name

open UserTableSize
fetch next from UserTableSize into @UserTableName
while @@fetch_status = 0
begin
Insert ##TempTable
exec sp_spaceused @UserTableName
fetch next from UserTableSize into @UserTableName
end
close UserTableSize
deallocate UserTableSize
Select *  from ##TempTable
--Drop Table ##TempTable
Set statistics time off
GO

Given below is one of the server execution times.
SQL Server Execution Times:
CPU time = 125 ms, elapsed time = 1034 ms.

Method 3 :
This method will not loop all the tables in the database one by one and also you don’t need to insert its result set into a temporary table to utilize it further. The performance of this method is also better than the other two methods also.
Given below is the script.

Set statistics time on
declare @PageSize float
select @PageSize=v.low/1024.0 from master.dbo.spt_values v where v.number=1 and v.type='E'

Select object_Name(i.object_id) as [name]
,p.rows
,Convert(varchar(50),@PageSize * SUM(total_pages)) + ' KB' as [reserved]
,Convert(varchar(50),@PageSize * SUM(CASE WHEN a.type <> 1 THEN a.used_pages WHEN p.index_id < 2 THEN a.data_pages ELSE 0 END)) + ' KB' as [data]
,Convert(varchar(50),@PageSize * SUM(a.used_pages - CASE WHEN a.type <> 1 THEN a.used_pages WHEN p.index_id < 2 THEN a.data_pages ELSE 0 END)) +  ' KB' as [index_size]
,Convert(varchar(50),@PageSize * SUM(total_pages-used_pages)) +  ' KB' as [unused]
FROM sys.indexes as i
JOIN sys.partitions as p ON p.object_id = i.object_id and p.index_id = i.index_id
JOIN sys.allocation_units as a ON a.container_id = p.partition_id
JOIN sys.tables t ON i.object_id=t.object_id
Where i.type<=1 and a.type=1
and
t.type='U' and is_ms_shipped=0
Group By i.object_id,p.rows
GO
Set statistics time off

Given below is the server execution times.

SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 6 ms.

Conclusion :
You can see that all the above methods produce the same result set but the issue is with the performance. I recommend Method 3 because it will take less effort and time to generate the same result set.

Any comments ?

Read Full Post »

I came across a question in the Forum, how to calculate the growth of all databases in a server.
So, I set out with my research for the best solution.

Given below are the two methods to calculate the growth of all databases in the server:

  • Via sp_MSforeachdb
  • Via sys.master_files

Given below is the workout that will help you understand the best way to calculate.

  • sp_MSforeachdb

Lets execute sp_MSforeachdb and view the statistics time.

SET STATISTICS TIME ON
exec sp_MSforeachdb 'use [?]; EXEC sp_helpfile'
--OUTPUT

autogrowthsettings1.1

After executing the above statement, I saw few server executions of sp_MSforeachdb. Given below is one of the server executions.
SQL Server Execution Times:
CPU time = 343 ms, elapsed time = 10050 ms.

  • sys.master_files

Given below is the query that  I copied from MS SQL Server profiler & modified it. (Just view growth from SSMS; you can find this query in the profiler)

SELECT
S.[name] AS [Logical Name]
,S.[file_id] AS [File ID]
, S.[physical_name] AS [File Name]
,CAST(CAST(G.name AS VARBINARY(256)) AS sysname) AS [FileGroup_Name]
,CONVERT (varchar(10),(S.[size]*8)) + ' KB' AS [Size]
,CASE WHEN S.[max_size]=-1 THEN 'Unlimited' ELSE CONVERT(VARCHAR(10),CONVERT(bigint,S.[max_size])*8) +' KB' END AS [Max Size]
,CASE s.is_percent_growth WHEN 1 THEN CONVERT(VARCHAR(10),S.growth) +'%' ELSE Convert(VARCHAR(10),S.growth*8) +' KB' END AS [Growth]
,Case WHEN S.[type]=0 THEN 'Data Only'
WHEN S.[type]=1 THEN 'Log Only'
WHEN S.[type]=2 THEN 'FILESTREAM Only'
WHEN S.[type]=3 THEN 'Informational purposes Only'
WHEN S.[type]=4 THEN 'Full-text '
END AS [usage]
,DB_name(S.database_id) AS [Database Name]
FROM sys.master_files AS S
LEFT JOIN sys.filegroups AS G ON ((S.type = 2 OR S.type = 0)
AND (S.drop_lsn IS NULL)) AND (S.data_space_id=G.data_space_id)
--OUTPUT

autogrowthsettings1.2
After executing the above query, I saw server execution of sys.master_files and I was really impressed.

SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 3 ms.

Conclusion :
Why there is a vast difference between two methods even though the output is almost the same ? Because sp_MSforeachdb runs sp_help against each database but on the other hand sys.master_files has all the data and you just need to present it.
The second difference between both is, if you need to modify sp_MSforeachdb result set, you need to insert it into temporary table and use it but in sys.master_files result set, you can do whatever you want without using any temporary table.

Let me know if you know other sound method to check auto growth settings of all databases.

Read Full Post »

In my last article, I had discussed how to convert a table from identity to sequence (manually). In this article, I would be sharing a script that I developed for one of my customers, to convert identity to sequence automatically. I presume that identity column belongs to integer data type family (small int, int, big int).
Note: Please test the script first on test database.

Given below is the example that we need to create, to understand the conversion:

Create table dbo.[Student]
(
[StudentID] int identity(1,1),
[StudentName] varchar(50)
CONSTRAINT PK_Student_StudentID PRIMARY KEY CLUSTERED
([StudentID] ASC)
)
GO
Insert into dbo.Student values ('Imran'),('Bob'),('Sandra')
GO
Select * from dbo.Student

identity_2_sequence1.1

Now, create the given below stored procedure to convert it automatically.

CREATE PROCEDURE Convert_Identity_To_Sequence_Proc
@Scheme_And_TableName nvarchar(Max)
AS

DECLARE @SQL AS NVARCHAR(MAX)
DECLARE @OBJECTID AS BIGINT
DECLARE @IDENTITY_COLUMN_NAME AS NVARCHAR(MAX)
DECLARE @DATA_TYPE_NAME AS SYSNAME
DECLARE @CONSTRAINT_NAME AS NVARCHAR(MAX)
DECLARE @Max_identity_ID AS BIGINT
DECLARE @ParmDefinition AS NVARCHAR(MAX)
DECLARE @TABLE_NAME AS NVARCHAR(MAX)

--Pick up object ID of the table
SELECT @OBJECTID=OBJECT_ID(@Scheme_And_TableName)
--Seperate Table name from the schema
SET @TABLE_NAME =SUBSTRING(@Scheme_And_TableName,CHARINDEX('.',@Scheme_And_TableName)+1,LEN(@Scheme_And_TableName))
Print @TABLE_NAME

--Check if the table has an identity table
If (Select Count(*) from sys.identity_columns where object_id =@OBJECTID)=0
BEGIN
RAISERROR('Could not found the identity column in this table',16,1)
RETURN
END
Print @OBJECTID

-- Pick identity column name , contraint name and data type name from the table.
SELECT @IDENTITY_COLUMN_NAME=A.name,@CONSTRAINT_NAME=B.name, @DATA_TYPE_NAME=D.name FROM sys.columns A
INNER JOIN sys.types D ON A.system_type_id =D.system_type_id
LEFT JOIN sys.indexes B ON A.object_id =B.object_id
LEFT JOIN sys.index_columns C ON B.object_id =C.object_id
AND B.index_id =C.index_id
AND A.column_id =C.column_id
WHERE A.is_identity =1 And A.object_id =@OBJECTID

Print @IDENTITY_COLUMN_NAME
Print @CONSTRAINT_NAME
Print @DATA_TYPE_NAME

-- Add a new column in the table that does not have the IDENTITY property with the same data type
SET @SQL ='ALTER TABLE ' + @Scheme_And_TableName +' ADD ' +@IDENTITY_COLUMN_NAME + 'New ' + @DATA_TYPE_NAME + ' NULL'
Print @SQL
EXEC (@SQL)

-- Copy values from the old column and update into the new column
SET @SQL ='UPDATE ' + @Scheme_And_TableName +' SET ' + @IDENTITY_COLUMN_NAME + 'New' + ' =' + @IDENTITY_COLUMN_NAME
Print @SQL
EXEC (@SQL)

-- Drop the primary key constraint from the old identity column
SET @SQL ='ALTER TABLE ' + @Scheme_And_TableName + ' DROP CONSTRAINT ' + @CONSTRAINT_NAME
Print @SQL
EXEC (@SQL)

-- Drop the old identity column
SET @SQL =' ALTER TABLE ' + @Scheme_And_TableName + ' DROP COLUMN ' + @IDENTITY_COLUMN_NAME
Print @SQL
EXEC (@SQL)

-- Rename the new column to the old columns name
SET @SQL ='EXEC sp_rename ' + ''''+ @Scheme_And_TableName + '.'+ @IDENTITY_COLUMN_NAME+'New' + '''' + ',' + ''''+ @IDENTITY_COLUMN_NAME + '''' + ',' + '''COLUMN'''
Print @SQL
EXEC (@SQL)

-- Change the new column to NOT NULL
SET @SQL ='ALTER TABLE ' + @Scheme_And_TableName + ' ALTER COLUMN ' + @IDENTITY_COLUMN_NAME + ' ' + @DATA_TYPE_NAME + +' NOT NULL'
Print @SQL
EXEC (@SQL)

-- Add the unique primary key constraint again with the same name
IF @CONSTRAINT_NAME IS NOT NULL
BEGIN
SET @SQL ='ALTER TABLE ' + @Scheme_And_TableName + ' ADD CONSTRAINT ' + @CONSTRAINT_NAME +' PRIMARY KEY CLUSTERED (' + @IDENTITY_COLUMN_NAME +' ASC)'
Print @SQL
EXEC (@SQL)
END
ELSE
BEGIN
PRINT 'NO CONSTRAINT'
END
-- Get the highest current value from the column
-- to use it for sequence creation.
SET @SQL ='SELECT @Max_ID=MAX(' + @IDENTITY_COLUMN_NAME + ') FROM ' + @Scheme_And_TableName
SET @ParmDefinition = N'@Max_ID ' + @DATA_TYPE_NAME + ' OUTPUT'
Print @SQL
Print @ParmDefinition
EXECUTE sp_executesql @SQL, @ParmDefinition,@Max_ID=@Max_identity_ID OUTPUT;
Print @Max_identity_ID

-- Use the next Identity value as the START WITH VALUE;
SET @SQL ='CREATE SEQUENCE ' + @Scheme_And_TableName + 'Seq' +
' AS ' + @DATA_TYPE_NAME +
' START WITH ' + try_Convert(varchar(max),@Max_identity_ID+1) +
' INCREMENT BY 1 ' ;
Print @SQL
EXEC (@SQL)

-- Add a default value of sequence to the column
SET @SQL ='ALTER TABLE ' + @Scheme_And_TableName + ' ADD CONSTRAINT Def' + @TABLE_NAME + ' DEFAULT (NEXT VALUE FOR ' + @Scheme_And_TableName + 'Seq)
FOR ' + @IDENTITY_COLUMN_NAME;
Print @SQL
EXEC (@SQL)

GO
--Execute the stored procedure and provide schema and table name as a parameter.
EXEC Convert_Identity_To_Sequence_Proc 'dbo.Student'

Insert few records and check whether the table is properly converted from identity to sequence or not.

Insert into Student (StudentName) Values ('Mark')
Insert into Student (StudentName) Values ('Peter')
Select * from dbo.Student
--OUTPUT

identity_2_sequence1.2

Reference : MSDN

Read Full Post »

In my earlier article, I wrote about sequence. In this article, we will learn how to convert an identity column to sequence, step by step. Original script is available here (MSDN)
Given below is the example that we need to create, to understand the steps :

Create table dbo.[Student]
(
[StudentID] int identity(1,1),
[StudentName] varchar(50)
CONSTRAINT PK_Student_StudentID PRIMARY KEY CLUSTERED
([StudentID] ASC)
)
GO
Insert into dbo.Student values ('Imran'),('Bob'),('Sandra')
GO
Select * from dbo.Student

identity_2_sequence1.1

Step :1
First of all, we need to add another column in the table with the same data type as identity column.

ALTER TABLE dbo.Student ADD StudentIDNew int NULL
GO

Step :2
Update the IDs from identity column to the newly added column.

UPDATE dbo.Student
SET [StudentIDNew] = [StudentID]
GO

Step :3
Drop the primary key constraint from the identity column of the table.

ALTER TABLE dbo.Student
DROP CONSTRAINT PK_Student_StudentID;
GO

Step :4
Drop the identity column from the column.

ALTER TABLE dbo.Student
DROP COLUMN [StudentID] ;
GO

Step :5
Rename the new column name to the old identity column name.

EXEC sp_rename 'dbo.Student.StudentIDNew',
'StudentID', 'COLUMN';
GO

Step :6
Change the new identity column to NOT NULL.

ALTER TABLE dbo.Student ALTER COLUMN [StudentID] int NOT NULL ;
GO

Step :7
Add primary key constraint back to the table.

ALTER TABLE dbo.Student
ADD CONSTRAINT PK_Student_StudentID PRIMARY KEY CLUSTERED
([StudentID] ASC) ;
GO

Step :8
Now, we need to create the sequence but before sequence creation, we need to know the last ID of the identity column.

SELECT MAX(StudentID) FROM dbo.Student ;
GO

Step :9
Create the sequence using the maximum ID +1 and the same data type of the identity column.

CREATE SEQUENCE dbo.StudentSeq
AS int
START WITH 4
INCREMENT BY 1 ;
GO

Step :10
Make the sequence as a default value of the column.

ALTER TABLE dbo.Student
ADD CONSTRAINT Const_StudentSeq DEFAULT (NEXT VALUE FOR dbo.StudentSeq)
FOR StudentID;
GO

Step :11
Insert few records and check whether the table is properly converted from identity to sequence or not.

Insert into Student (StudentName) Values ('Mark')
Insert into Student (StudentName) Values ('Peter')
Select * from dbo.Student
--OUTPUT

identity_2_sequence1.2

Shall discuss how to change a table from identity to sequence automatically in my next post.

Read Full Post »

I received a request to add a column in the entire table of the database for a customer. It was so simple that I made the script as given below and told them to run it first and then again run its result set in SQL server, so all tables would be altered. It appeared that the Job was done but unfortunately it was not. One thing I forgot to mention is that the client environment in SQL Server 2012. If you look at the query it will perform alter table in all user table.

Select 'Alter Table ' + quotename(schema_name([schema_id])) +'.' + quotename([name])
+ ' ADD [GUID] uniqueidentifier default newid()' from sys.tables

filetableidentify1.1

Ooops… it generated an error.

Msg 33422, Level 16, State 1, Line 4
The column ‘GUID’ cannot be added to table ‘dbo.DataBank’ as it is a FileTable.
Adding columns to the fixed schema of a FileTable object is not permitted.
filetableidentify1.2

The reason behind this error is that I made an alter statement for even the File Table, while you cannot add any column in the File Table.

I, therefore, need to remove the file table from the query result set. So I did a little research and found that if you use the column is_filetable (data type bit) in sys.tables, you can easily identify whether it as a file table  or not . If is_filetable  is 1, then the table is a File Table else not.
So, I changed the query and it worked perfectly. Now you can see that the query will only generate the script for normal table (not file tables).

Select 'Alter Table ' + quotename(schema_name([schema_id])) +'.' + quotename([name])
+ ' ADD [GUID] uniqueidentifier default newid()' from sys.tables where is_filetable =0

filetableidentify1.3

Let me know if you know other ways to find file table as well.

Read Full Post »

« Newer Posts - Older Posts »