Showing posts with label TSQL. Show all posts
Showing posts with label TSQL. Show all posts

Friday, July 13, 2012

Add Numbers from string(varchar) in tsql

Once I was asked by my colleague to write a function which will add the numbers from a string, so I write a function for it. I used the TSQL substring,  Len, ASCII and char functions to achieve this task.

Code Snippet:
CREATE FUNCTION SelectNumbersFromString(@str varchar(50)) RETURNS varchar(MAX) AS BEGIN DECLARE @cchk char(5); DECLARE @len int ; DECLARE @aschr int;
SET @len =
  (SELECT len(@str)); DECLARE @count int
SET @count = 1 DECLARE @ans varchar(MAX)
SET @ans = '' While @count <= @len BEGIN
SET @cchk =
  (SELECT Substring(@str,@count,1));
SET @aschr =
  (SELECT ASCII(@cchk)); IF @aschr IN (49,
                                       50,
                                       51,
                                       52,
                                       53,
                                       54,
                                       55,
                                       56,
                                       57,
                                       58) BEGIN
SET @ans = @ans + CHAR(@aschr) END
SET @count = @count + 1; END RETURN @ans; END

Wednesday, May 9, 2012

SQL CLR Table Valued Function

SQL CLR project allows the developers to write code in .Net. In this post I will create a SQL CLR function that will return a table as a result.
For those people who did not knew how to create a Sql Clr project first take a look at the following post
Creating Sql Clr Stored Procedure
After creating a SQL CLR project. From the Project Menu or Add New Item dialog box add a new class file. In the class create a function having return type IEnumerable and add the SqlFunction attribute to header of your function as shown below:
public partial class Functions  
 {  
   [Microsoft.SqlServer.Server.SqlFunction]  
   public static IEnumerable fn_getData()  
   {  
      ArrayList rowsArray = new ArrayList();  
      return rowsArray;  
   }  
 }  

Now add the FillRowMethodName and TableDefinition parameters to the SqlFunction attribute. Set FillRowMethodName = "FillRow". The FillRow method is implicity called by the SQL CLR framework each time the MoveNext() on the returned IEnumerable ( type that implements IEnumerable interface ) is called. In TableDefinition specify the columns of the table. See the below code

[Microsoft.SqlServer.Server.SqlFunction(FillRowMethodName="FillRow",TableDefinition="Name nvarchar(30), Age int, City nvarchar(30)")]  
   public static IEnumerable fn_getData()  
   {  
     ArrayList rowsArray = new ArrayList();  
     return rowsArray;  
   }  

Now we will create a function SetData in which we will fill the arraylist with some data.
 public static void SetData(ArrayList rowsArray)
     {
        object[] column = new object[3];
        column[0] = "John";
        column[1] = 18;
        column[2] = "Newyork";
        rowsArray.Add(column);
     }
After this we will finally write the FillRow method. This method will write the row by row data of ArrayList to the table. It has an object parameter which will give the row of an arrayList. The signature of FillRow method is
private static void FillRow(Object obj, out [col1_type] [column Name], ... )

In FillRow method we will store the obj in an object Array and cast the columns to their respective types as shown below:

public static void FillRow(object obj, out string Name, out int Age, out string City)  
    {  
     object[] row = (object[])obj;  
     Name = (string)row[0];  
     Age = (int)row[1];  
     City = (string)row[2];  
   }  

It gets called once each time the framework calls .MoveNext() on the underlying ArrayList method (which implements the inherited IEnumerable interface)

The complete code is below:

public partial class Functions  
 {  
   [Microsoft.SqlServer.Server.SqlFunction(FillRowMethodName="FillRow",TableDefinition="Name nvarchar(30), Age int, City nvarchar(30)")]  
   public static IEnumerable fn_getData()  
   {  
     ArrayList rowsArray = new ArrayList();  
     SetData(rowsArray);  
     return rowsArray;  
   }  
    public static void FillRow(object obj, out string Name, out int Age, out string City)  
    {  
     object[] row = (object[])obj;  
     Name = (string)row[0];  
     Age = (int)row[1];  
     City = (string)row[2];  
   }  
    public static void SetData(ArrayList rowsArray)  
    {  
     object[] column = new object[3];  
     column[0] = "John";  
     column[1] = 18;  
     column[2] = "Newyork";  
     rowsArray.Add(column);  
     object[] column1 = new object[3];  
     column1[0] = "Scott";  
     column1[1] = 25;  
     column1[2] = "Washington";  
     rowsArray.Add(column1);  
   }  
 }  

Now deploy the project and move to Sql Server. Open the database in which you have deployed the function. I have used NorthWind database. I ran this query and got the desired output


References:
http://msdn.microsoft.com/en-us/library/ms131103(v=sql.90).aspx
http://blogs.msdn.com/b/stuartpa/archive/2005/07/21/441468.aspx

Sunday, April 29, 2012

Creating a SQL CLR Stored Procedure using VS 2010 and Sql Server 2008

SQL CLR give us the ability to write code in .Net Framework. In Visual Studio 2005,8 and 10 there is a database project namely SQL CLR Database project as shown in the below image.
Before creating the project please change the .net framework version to .net Framework 3.5 from the drop down menu.
After choosing the template you have to choose a database in which you will deploy the solution. The following window will open when you press OK button.
We will use Northwind database. Press the OK button. The following window will open

To enable the debugging press  the Yes button otherwise No. Now the project is created. The project consists of following folders and files.
Now from the project menu select stored procedure to add a code file.
Add the stored procedure and give a name to it. We gave a name sp_WriteFile to it. We use the File Class method WriteAllText to write a file to the Sytem. The complete code consists of only one line as shown in the below image.

The sp has two parameters FileName and FileContent. Now go to project properties select Database tab and set the Permission Level to external or Unsafe. By default permission level is set to Safe.


We changed the permission level because we have to access the File System. In Safe permission level we can 't access the file system.
Read more about the permission levels at MSDN

Now deploy the solution.

When you deploy the project the following error may appears.

//C:\Code\CLRProject\CLRProject\bin\Debug\CLRProject.sql(106-106): Deploy error SQL01268: .Net SqlClient Data Provider: Msg 10327, Level 14, State 1, Line 1 CREATE ASSEMBLY for assembly 'CLRProject' failed because assembly 'CLRProject' is not authorized for PERMISSION_SET = EXTERNAL_ACCESS. The assembly is authorized when either of the following is true: the database owner (DBO) has EXTERNAL ACCESS ASSEMBLY permission and the database has the TRUSTWORTHY database property on; or the assembly is signed with a certificate or an asymmetric key that has a corresponding login with EXTERNAL ACCESS ASSEMBLY permission.  
// An error occurred while the batch was being executed.  
// Build FAILED.  

As the message explains, SQLCLR code with the EXTERNAL_ACCESS permission set must either be signed or the database must be given the TRUSTWORTHY attribute. Let's make the database TRUSTWORTHY with this ALTER DATABASE statement:

ALTER DATABASE Northwind SET TRUSTWORTHY ON  

Another problem is of database ownership as mentioned in the message "database owner (DBO) has EXTERNAL ACCESS ASSEMBLY permission" so change the owner of the database to sa. Run the following command

EXEC sp_changedbowner sa  

CLR Integration must be enabled in order to use SQL CLR objects. By Default CLR Intergration is disabled so we first have to enable it.
Run the following script to enable Sql CLR integation.
sp_configure 'show advanced options', 1;  
 GO  
 RECONFIGURE;  
 GO  
 sp_configure 'clr enabled', 1;  
 GO  
 RECONFIGURE;  
 GO  

Now again deploy the solution. After deployment open the Sql Server Management Studio. Select Northwind database and open the stored procedures folder and the assemblies folder. See the below image.
As shown in the image sp_WriteFile is added to stored procedures and an assembly of CLRProject is added to the Assemblies folder.

References:
Enabling CLR Integration
CLR Integration Code Access Security
http://www.mssqltips.com/sqlservertip/1662/writing-to-an-operating-system-file-using-the-sql-server-sqlclr/

Tuesday, March 27, 2012

Steps to enable CLR Integration, OLE Automation and xp_cmdshell procedures in sql server 2005 and 2008

For SQL Server 2005:
Follow these steps:
1) From start menu open Sql Server 2005 surface are configuration
2) Select Surface Area Configuration For Features
Select OLE Automation from Database Engine node and then checked the Enable OLE Automation checked box to enable the feature. Follow the same step for CLR Integration and xp_cmdshell. Then click the apply button and close the window. The CLR Integration, OLE Automation features and xp_cmdshell features are now enabled.


For SQL Server 2008:
1) Open the SQL Server 2008 and follow the below steps
After performing the above steps click he OK button.  The OLE Automation features and xp_cmdshell features are now enabled.
To enable CLR Integration select the server configuration from the drop down menu.




Change the ClrIntegrationEnabled value from false to true to enable it. Now CLR Integration is enabled.
or run the following script to enable CLR Integration

sp_configure 'show advanced options', 1;   
  GO   
  RECONFIGURE;   
  GO   
  sp_configure 'clr enabled', 1;   
  GO   
  RECONFIGURE;   
  GO   


Reference:
http://msdn.microsoft.com/en-us/library/ms161956.aspx

Reading and Writing Files using T-SQL ( Sql Server )

Reading a File:

OPENROWSET is a T-SQL function that allows reading data from many sources including using the SQL Server’s BULK import capability. One of the useful features of the BULK provider is its ability to read individual files from the file system into SQL Server, such as loading a data from a text file or a Word document into a SQL Server table.

The BULK option was added to T-SQL in SQL Server 2005 and it persists in SQL Server 2008.
When used with the BULK provider keyword you can name a data file to read as one of three types of objects:
  1. SINGLE_BLOB, which reads a file as varbinary(max)
  2. SINGLE_CLOB, which reads a file as varchar(max) 
  3. SINGLE_NCLOB, which reads a file as nvarchar(max) 
OPENROWSET returns a single column, named BulkColumn, as its result. Here’s an example that reads a text file:
Query:
SELECT BulkColumn 
FROM OPENROWSET (BULK 'C:\Test\test.txt', SINGLE_CLOB) MyFile
Output:

Writing a File:

1) Write a File using  xp_cmdshell:
Before using xp_cmdshell, we first have to enable xp_cmdshell feature, due to security reasons it is disabled by default.
See the following post
Steps to enable OLE Automation and xp_cmdshell procedures in sql server 2005 and 2008
                                                                     OR
EXEC sp_configure 'show advanced options', 1

GO

--- To update the currently configured value for advanced options.

RECONFIGURE

GO

-- To enable the feature.

EXEC sp_configure 'xp_cmdshell', 1

GO

--- To update the currently configured value for this feature.

RECONFIGURE

GO  
Query:
Declare @text varchar(max)
Declare @data cursor
Declare @a varchar(20)
Declare @b varchar(30)
DECLARE @cmd sysname, @var sysname

SET @data = Cursor for
Select FirstName,LastName from dbo.Employees // Northwind database


Open @data
WHILE (1 <> 0)
BEGIN

    FETCH NEXT FROM @data INTO @a , @b

    SET @text ='First Name :'+@a+' and Last Name :'+@b

    IF ( @@FETCH_STATUS <>  0 )
    BEGIN
        BREAK;
    END

SET @cmd = 'echo ' + @text + ' >> c:\var_out.txt'
exec master..xp_cmdshell @cmd

END
In the above code, we declare a cursor  @data in which we stored first name and last name of employees and then open the @data cursor and place an infinite while loop. The IF condition is placed inside the while loop to check @@Fetch_Status. The loop will continue works until the @@Fetch_Status does not return 0.
In the end the records are written to the var_out.txt file. There are multiple records in the employees table, all of them are appended in the same file.

2) Using OLE Automation Stored Procedures:
CREATE PROCEDURE sp_OAToFile(@FileName varchar(255), @Text1 text) AS
DECLARE @FS int, @OLEResult int, @FileID int

EXECUTE @OLEResult = sp_OACreate 'Scripting.FileSystemObject', @FS OUT
IF @OLEResult <> 0 PRINT 'Scripting.FileSystemObject'

--Open a file
execute @OLEResult = sp_OAMethod @FS, 'OpenTextFile', @FileID OUT, @FileName, 8, 1
IF @OLEResult <> 0 PRINT 'OpenTextFile'

--Write Text1
execute @OLEResult = sp_OAMethod @FileID, 'WriteLine', Null, @Text1
IF @OLEResult <> 0 PRINT 'WriteLine'

EXECUTE @OLEResult = sp_OADestroy @FileID
EXECUTE @OLEResult = sp_OADestroy @FS

GO

SET QUOTED_IDENTIFIER OFF
GO 
SET ANSI_NULLS ON
GO
In the above code, we created a stored procedure which takes two parameters file name and text. File name is the name of the file which will be created and text is the content which is written to the file.
sp_OACreate creates an instance of OLE object.
sp_OAMethod calls the method of OLE object.
and last one sp_OADestroy procedure destroys the OLE object.

References:
OLE Automation Stored Procedures.
http://msdn.microsoft.com/en-us/library/ms190501(v=sql.110).aspx
Read file reference
http://www.mssqltips.com/sqlservertip/1643/using-openrowset-to-read-large-files-into-sql-server/

Friday, February 17, 2012

Important MS SQL server system Views

Microsoft SQL server has a lot of built in system views which provides information about almost all of the objects in the database. Let's talk about the most important system views:

1)sys.databases
This view will return all the databases in the instance of a Sql Server.

Columns:
name ( datatype sysname ) of database is unique with in the instance of a SQL Server
database_id ( datatype int ) of database is unique with in the instance of a SQL Server
Database state ( type tinyint ) :
0 = ONLINE
1 = RESTORING
2 = RECOVERING
3 = RECOVERY_PENDING
4 = SUSPECT
5 = EMERGENCY
6 = OFFLINE


2) sys.objects
This view provides information about all of the objects in the selected database. 

The name ( datatype sysname ) is the name of the object.
The object_id ( datatype int ) is unique with in the database.
The type column ( datatype char(2) ) specifies whether it is a function, procedure or a table etc.

Important types are given below.
AF = Aggregate function (CLR)
C = CHECK constraint
D = DEFAULT (constraint or stand-alone)
F = FOREIGN KEY constraint
FN = SQL scalar function
FS = Assembly (CLR) scalar-function
FT = Assembly (CLR) table-valued function
IF = SQL inline table-valued function
IT = Internal table
P = SQL Stored Procedure
PC = Assembly (CLR) stored-procedure
PG = Plan guide
PK = PRIMARY KEY constraint
R = Rule (old-style, stand-alone)
RF = Replication-filter-procedure
S = System base table
SN = Synonym
SQ = Service queue
TA = Assembly (CLR) DML trigger
TF = SQL table-valued-function
TR = SQL DML trigger
TT = Table type
U = Table (user-defined)
UQ = UNIQUE constraint
V = View
X = Extended stored procedure

Example:
select * from sys.objects     
where type='V'
            OR
select * from sys.views
--Both queries will bring the same result.
3) sys.procedures
This procedure will return all the procedures from the selected database
3) sys.tables
This view will returns all the tables from the selected database
4) sys.views 
This view will return all the views from the selected database.
5) sys.triggers;
This view will return all the triggers from the selected database.

6) sys.columns
This will retrun all the columns of the objects ( Table,Views etc ) in the selected database

Source:
MSDN
Read more at