Wednesday, 6 January 2016

Easy SQL Server Tool Using C#

Reader Level:
Article

Easy SQL Server Tool Using C#

By Syed Shanu on Jan 04, 2016
In this article we will see how to create an easy SQL Server Tool.
Introduction
 
My previous article explained how to design a form at runtime,
In this article we will see how to create an Easy SQL Server Tool.
Easy SQL Server Tool will allow users to create SQL Server Database, Delete Database, Load all Database Names from a SQL selected Server, Create a New Table, Insert records to Table, Select Records from Table and bind the result to grid, Export the selected result to CSV file format, Delete Table, Delete ALL Records from a table without writing any SQL Script.
We have used SQL Server Management Objects (SMO) to programmatically create SQL Server Database, Table, etc.
What is SQL Server Management Objects (SMO)?
SQL Server Management Objects (SMO) is a collection of objects to manage SQL Server programmatically. Using SMO objects we can programmatically connect to SQL server, Get collections of all Database names, Create new Database, Backup Database, Restore Database, Create Table, Get collections of Table Name for a given Database, Get all Column details of a given Table, etc.
Reference website: To learn more detail about SQL Server SMO kindly view all these links,
Features in Shanu Easy SQL Server Tool (SESST)
  1. Connect to SQL Server.
  2. Table Details
  3. SQL Script Tab (Create Table tab / Insert and Delete records tab / Select Query tab).
  4. Output Window
Here we will see details of each part,
Step 1: Connect to SQL Server,


SQL Server Connect We can connect to any SQL Server within our network. We need to give SQL Server Name or IP Address, SQL Server Login ID and password to connect to SQL Server.
Create New Database
Check that the user entered Database name exist in SQL Server or not. If it exists, then display the message to user. If there is no database with user entered name then new Database will be created.
 
  Load Database
Load all the Database Name to combobox for creating Table.
Delete Database
User can delete the selected Database from SQL Server. Before deleting confirmation box will be displayed to user to delete or not. If user click on ok then the selected database will be deleted.
 
 
Database Backup Backup the selected Database to any folder as you have selected.
 
 
Database Restore User can restore the database by selecting “.bak” file from the selected folder.


 

Step 2: Table Details

 
Load Table:

User need to first select the Database to list all the Table Names. After selecting the database and by clicking on the Load Table Names all the Table Names to the Combobox will be loaded. Delete Table
User can delete the selected Table from SQL Server. Before deleting confirmation box will be displayed for user to delete or not. If user click on ok then the selected Table will be deleted.

Step 3: SQL Script Tab
Here we will be having 3 tab, first tab is for creating Table, second tab is for Insert and Delete Records and the last third tab is for selecting query. We will see all three tab details here.
Create Table Tab
 
 
Here user can create their own table without writing SQL Query. Firstly, user need to select the Database where the table needs to be created. After selecting the Database user can enter their SQL Table Name in the textbox. After entering the table name user need to add columns for that Table. Without adding columns the Table cannot be created. Adding Columns
 

User can add columns for creating new Table. All these columns will be added locally to the grid for finally creating a Table. User can add any number of columns, delete the selected column and also delete all columns by clicking on Clear Columns. Adding and deleting columns do not deal with database so this will be as temp place to add columns for creating Table. After adding all columns for the Table user can click on Create Table button to create a new Table with given column details. Datatype:
Here for now only 3 datatypes have been used.
  1. Int (Numbers)
  2. varchar (for text)
  3. nVarchar (for Numbers and text)
User can also add each column data size. For integer the size will not be used, but for Varchar and nVarchar Datatype user can add the column data size. User can also set Max size for both Varchar and nVarchar type by selecting the Max Size checkbox.
For example, we can see the following image. Here we have added 4 columns to the grid and adding one more new column we can see each column Datatype and Size from the grid. After adding all column, we click the Create Table Button. We can see the confirmation message as Table was created and also we can see our new Table has been added in the Table List Combobox.
 
 
Insert and Delete Records Tab We will be using the recently created test Table for inserting demo.
 
Here we can see in the above image we have selected the Table “test” from Table List. To insert record to selected Table we need to click on the load table Details to insert button. By clicking this we will be displaying all the column name with textbox. Depending on the Datatype of each column we will be adding textbox with maxlength. If the column datatype is Integer then we will be adding Numeric textbox for that column' by this user can enter only numbers to that textbox. For Varchar and nVarchar we will check for each Column Size if its max then we set the textbox maxlength as 200; by this user can enter only 200 characters. If size is set for column then we will be setting the column size for textbox maxlength. Insert:
 
 
After loading all the column details with TextBox user can enter the value to be inserted for each column. Once user entered the value click on the Insert into Selected Table button for inserting a new record. Same like this user can enter any number of records for the selected table. If you want to add more functionality from the code you can add your functionality, for example, like checking duplicate value before insert and etc. Delete All Records: User can delete all records of the selected table. Here in this sample we are not checking any condition for deleting the records. If you need to add more functionality you can change from the code and add your own functions, for example like Delete records of a table based on condition and etc.
Select Query Tab
 
 
For selecting the records from a Database and display the result user need to first select the Database and then select the Table from the Table List to create a SQL Select query.
User can select the details using three features,
1) All Columns: If All Columns checkbox is checked then all column details result will be displayed to the output window grid. (This is same like * in select query, for example select * from tablename). We can see from the above image The All Column Check box will be loaded by default. After selecting the table and when user clicks on Run Select Query all column details will be loaded in the following output window grid.
2) User selected Columns: If user want to display only particular columns of the table then they can click on load Table Columns to Select button to display all the column name of the tables to CheckedListbox. Here user can select the columns they need and by default checked all the Column Names. User can uncheck the columns which are not needed and also uncheck the All Columns Checkbox to display only selected columns as a result.
User can Write SQL Select Query: User can also write their SQL Select query to display the output.
 
 
 
For example, if user want to write their own SQL query to join 3 table and display the result. To write SQL Select query user need to check the SQL Select Query checkbox and after writing select query user can click on Run Select Query button to see the result. In the above image we can see, we wrote a sample SQL Join query to join the three table and by clicking the Run Select Query the result has been bind in the grid.
SQL Injection Checking in user entered select query:
 

We have also checked for the SQL Injection before executing user entered SQL Select query. We have created an array list to add all SQL injection string and we will be checking any of the array word is matching with user entered select query. For example, we can see the above image since after select query we have entered drop query. But when we click on Run Select Query button we display the message as drop is not accepted in select query.
Here is the list of SQL Injection string I am checking if you need you can add or remove as per your requirement.
  1. string[] sqlInjectionArray = { "create""drop""delete""insert""update""truncate","grant ","print","sp_executesql ,"objects","declare","table","into",  
  2. "sqlcancel","sqlsetprop","sqlexec","sqlcommit","revoke","rollback","sqlrollback","values","sqldisconnect","sqlconnect","user","system_user","use","schema_name","schemata","information_schema","dbo","guest","db_owner","db_","table","@@","Users","execute","sysname","sp_who","sysobjects","sp_","sysprocesses ","master","sys","db_","is_","exec""end""xp_","; --""/*""*/""alter""begin""cursor""kill","--" ,"tabname","or","sys"};  
Save Select Query: User can also save the Select Query as text file to selected folder for using the select query later.

 
 
 Open saved Select Query: User can also open the saved Select Query to execute the select script.
 
 
 
Export the Result to CSV file Format: User can also export the selected result to CSV format. Here in the following image we can see the result has been exported as CSV file.
 
 

Prerequisites
Visual Studio 2015: You can download it from here.
SQL SERVER SMO Reference: For working with SQL Server SMO we need to add 4 important reference to our project,
  • Microsoft.SqlServer.ConnectionInfo.dll
  • Microsoft.SqlServer.Smo.dll
  • Microsoft.SqlServer.Management.Sdk.Sfc.dll
  • Microsoft.SqlServer.SqlEnum.dll
You can find the reference from this path (Here we have used SQL Server 2014),
C:\Program Files\Microsoft SQL Server\120\SDK\Assemblies\
Add all these 4 Assembly reference to your project,

 
 
Code part The main aim was to create a simple and easy to use Easy SQL Tool. All the functionalities has been added in one main form with Tab. We have created 2 class:
  1. smoSQLServerClass: In this class we have created function to Connect, Disconnect to SQL Server, Create Database, Delete Database, Backup Database, Write all the Exception to Log text file to executable folder, Create Table etc.
  2. sqlBizClass: In this class we perform all business logic for our Main form for example like creating Dynamic query, Creating Dynamic Controls and bind to panel, Bind all Table names returned from SMOSQLServerClass to Combobox controls ,Check SQL injection for Select query and return the result as true or false etc. 
Here we will see some important code part used in the Easy SQL Server Tool. All the code part has been well-commented, so the user can easily understand the code.
Connect to SQL Server
In this article I have mentioned for using SQL Server SMO objects we need to add 4 important Assembly reference to our project. Using SMO ServerConnection we can connect to SQL server. We need to set the SQL Server name to ServerInstance and set SQL Server login and password. After connecting we check for Connection is open and return the Boolean value to our main function to display the appropriate message to user.
  1. public bool SqlServerConnect()  
  2.         {  
  3.             try  
  4.             {  
  5.                 servConn = new ServerConnection();  
  6.                 servConn.ServerInstance = serverName;  
  7.                 servConn.LoginSecure = false;  
  8.                 servConn.Login = LoginID;  
  9.                 servConn.Password = password;  
  10.                 servConn.Connect();  
  11.                 if(servConn.IsOpen)  
  12.                 {  
  13.                     return true;  
  14.                 }  
  15.                 else  
  16.                 {  
  17.                     return false;  
  18.                 }  
  19.                  
  20.             }  
  21.             catch (Exception ex)  
  22.             {  
  23.                 writeLogMessage(ex.Message.ToString());  
  24.   
  25.             }  
  26.             return false;  
  27.         }  
Write Exception Message to Log File: We will be writing all exception error message to Log file with Date and Time.
  1. public void writeLogMessage(String logMessage)  
  2.         {  
  3.             string path = Application.StartupPath + @"\LogFile.txt";  
  4.             logMessage = logMessage + " - on " + DateTime.Now.ToString();  
  5.             if (!File.Exists(path))  
  6.             {  
  7.                 using (StreamWriter tw = File.CreateText(path))  
  8.                 {  
  9.                     tw.WriteLine(logMessage);  
  10.                     tw.Close();  
  11.                 }  
  12.             }  
  13.             else  
  14.             {  
  15.                 StreamWriter tr = new StreamWriter(path);  
  16.                 tr.WriteLine(logMessage);  
  17.                 tr.Close();  
  18.             }  
  19.         }  
Load Database Name In Load Database Name button click event, we will pass the comboBox control to the Biz class method. In biz class method we will call the SMO Class to get all the database name and add all the database name to combobox. Here in this method I will check for Master Database and will not add the name for security reason, for example user can delete the database from our main form. Similarly you can change the code to restrict any database that show it in our main form.
  1. public void loaddbNames(ComboBox cbo)  
  2.         {  
  3.             //return objSQL.loaddbNames();  
  4.             DatabaseCollection dbnamesCol = objSQL.loaddbNames();  
  5.             cbo.Items.Clear();  
  6.             cbo.Items.Add("");  
  7.             if (dbnamesCol != null)  
  8.             {  
  9.                 string dbnames = "";  
  10.                 int ival = 0;  
  11.                 foreach (Database db in dbnamesCol)  
  12.                 {                 
  13.   
  14.                     if (db.Name != "master")  
  15.                     {  
  16.                         cbo.Items.Add(db.Name);  
  17.                     }                   }  
  18.                 }  
  19.             cbo.SelectedIndex = 0;  
  20.         }  
In SMO Class we will be loading all the Database name for a given SQL Server and return as DatabaseCollection to calling class. 
  1. public DatabaseCollection loaddbNames()  
  2.         {  
  3.             DatabaseCollection dbNames = null;  
  4.             try  
  5.             {                 
  6.                 if (SqlServerConnect())  
  7.             {  
  8.                 Server srv = new Server(servConn);  
  9.                     dbNames = srv.Databases;  
  10.                     SqlServerDisconnect();  
  11.                 }  
  12.             }  
  13.             catch (Exception ex)  
  14.             {  
  15.                 writeLogMessage(ex.Message.ToString());  
  16.             }  
  17.             return dbNames;  
  18.         }  
Create Database In this function first we check for Database already exist with the user entered name. If database with same name do not exist we will create a new database in our SQL Server. If Database already exist in the SQL Server, then return the message as Database exist.
  1. public string createourDatabase(string DatabaseName)  
  2.         {  
  3.   
  4.             try  
  5.             {  
  6.                 if (SqlServerConnect())  
  7.                 {  
  8.                     Server srv = new Server(servConn);  
  9.   
  10.                     Database database = srv.Databases[DatabaseName];  
  11.                     if (database == null)  
  12.                     {  
  13.                         database = new Database(srv, DatabaseName);  
  14.                         database.Create();  
  15.                         database.Refresh();  
  16.                         SqlServerDisconnect();  
  17.                         return "Database Created Successfully !";  
  18.                     }  
  19.                     else  
  20.                     {  
  21.                         SqlServerDisconnect();  
  22.                         return "Database Already Exist";  
  23.                     }  
  24.                 }  
  25.                 else  
  26.                 {  
  27.                     return "Enter valid SQL Connection Details";  
  28.                 }  
  29.             }  
  30.             catch (Exception ex)  
  31.             {  
  32.                 writeLogMessage(ex.Message.ToString());  
  33.             }  
  34.             return "Sorry Error While creating DB";  
  35.         }  
Create Table In Create button click we will pass the user selected Database Name, User entered Table Name with Column Details as DataTable to SMO Class. In this function we will check for table already exist or not; if exist return false message to user and if not, then we will create a new Table with column details.
  1. public string createTable(string DatabaseName, string TableName,DataTable dtColumns)  
  2.         {  
  3.             try  
  4.             {  
  5.                 if (SqlServerConnect())  
  6.                 {  
  7.                     Server srv = new Server(servConn);  
  8.                     Database database = srv.Databases[DatabaseName];  
  9.                     if (database != null)  
  10.                     {  
  11.                         bool tableExists = database.Tables.Contains(TableName);  
  12.                         if (tableExists)  
  13.                         {  
  14.                             SqlServerDisconnect();  
  15.                             return "Table Already Exist.kindly Enter Different Table Name";  
  16.                         }  
  17.                         else  
  18.                         {  
  19.                             Table tbl = new Table(database, TableName);                   
  20.                             foreach (DataRow dr in dtColumns.Rows)  
  21.                             {  
  22.                                 string columnName = dr["ColumName"].ToString();  
  23.                                 string DataType = dr["DataType"].ToString();  
  24.                                 string dataSize = dr["Size"].ToString();  
  25.                                 Microsoft.SqlServer.Management.Smo.Column columntoAdd =null;                          
  26.                                 switch (DataType)  
  27.                                 {  
  28.                                     case "Varchar":  
  29.                                         if(dataSize=="max")  
  30.                                         {  
  31.                                             columntoAdd = new Column(tbl, columnName, Microsoft.SqlServer.Management.Smo.DataType.VarCharMax);  
  32.                                         }  
  33.                                         else if (dataSize != "")  
  34.                                         {  
  35.                                             columntoAdd = new Column(tbl, columnName, Microsoft.SqlServer.Management.Smo.DataType.VarChar(Convert.ToInt32(dataSize)));  
  36.                                         }  
  37.                                         break;  
  38.                                     case "Int":                                       
  39.                                             columntoAdd = new Column(tbl, columnName, Microsoft.SqlServer.Management.Smo.DataType.Int);                                       
  40.                                         break;  
  41.                                     case "nVarchar":  
  42.                                         if (dataSize == "max")  
  43.                                         {  
  44.                                             columntoAdd = new Column(tbl, columnName, Microsoft.SqlServer.Management.Smo.DataType.NVarCharMax);  
  45.                                         }  
  46.                                         else if (dataSize != "")  
  47.                                         {  
  48.                                             columntoAdd = new Column(tbl, columnName, Microsoft.SqlServer.Management.Smo.DataType.NVarChar(Convert.ToInt32(dataSize)));  
  49.                                         }  
  50.                                         break;  
  51.                                 }  
  52.                                 if(columntoAdd!=null)  
  53.                                 {   
  54.                                 tbl.Columns.Add(columntoAdd);  
  55.                                 }  
  56.                             }  
  57.                             tbl.Create();  
  58.                             SqlServerDisconnect();  
  59.                             return "Table Created Successfully !";  
  60.                         }                         
  61.                     }  
  62.                 }  
  63.                 else  
  64.                 {  
  65.                     return "Enter valid SQL Connection Details";  
  66.                 }  
  67.             }  
  68.             catch (Exception ex)  
  69.             {  
  70.                 writeLogMessage(ex.Message.ToString());  
  71.             }  
  72.             return "Sorry Error While Creating Table";  
  73.         }  
Load Column Details for Insert In Load Column details button click we will pass the Panel Control to our biz class to get all the column details of selected table and bind a text box with column name to panel. From our SMO Class we will get all the Column details of table and return as ColumnCollection. In biz class using foreach we will add all column details like Name as Label control to display the Column Name and add a Textbox for user input. In this method we will check for column type and column size. If the column type is Integer then we will set the Textbox as Numeric Textbox. If the column type is Varchar or NVarchar we check for column length and assign the length as TextBox Maxlenght.
  1. public void loadTableColumnDetails(Panel pnControls, string DataBaseName,string TableName)  
  2.         {             
  3.             ColumnCollection tableColumnDetail = objSQL.loadTableColumnDetails(DataBaseName, TableName);  
  4.             pnControls.Controls.Clear();  
  5.           
  6.             if (tableColumnDetail != null)  
  7.             {  
  8.                 string dbnames = "";  
  9.                 int lableHeight = 20;  
  10.                 int textboxHeight = 20;  
  11.                 int lablewidth = 100;  
  12.                 int lableXVal = 10;  
  13.                 int lableYVal = 10;  
  14.   
  15.                 foreach (Column colName in tableColumnDetail)  
  16.                 {  
  17.                     string s = colName.Name;  
  18.   
  19.                     Random rnd = new Random();  
  20.                     int randNumber = rnd.Next(1, 1000);  
  21.   
  22.                     //to add Column name to display as caption  
  23.                     Label ctrl = new Label();  
  24.                     ctrl.Location = new Point(lableXVal , lableYVal+6);  
  25.                     ctrl.Size = new Size(lablewidth , lableHeight);  
  26.                     ctrl.Name = "lbl_" + randNumber; ;  
  27.                     ctrl.Font = new System.Drawing.Font("NativePrinterFontA", 7F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));  
  28.                     ctrl.Text = colName.Name;  
  29.                     pnControls.Controls.Add(ctrl);  
  30.   
  31.                     //to add textbox for user enter insert text  
  32.                     TextBox ctrltxt = new TextBox();  
  33.                     ctrltxt.Location = new Point(lableXVal+110, lableYVal);  
  34.                     ctrltxt.Size = new Size(lablewidth+40, lableHeight);  
  35.                     ctrltxt.Name = "txt_" + randNumber;  
  36.                     ctrltxt.Font = new System.Drawing.Font("NativePrinterFontA", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));  
  37.                     ctrltxt.Text = "";  
  38.                       
  39.                     if (colName.DataType.Name== "int")  
  40.                     {  
  41.                         ctrltxt.MaxLength = 20;  
  42.                         ctrltxt.KeyPress += new KeyPressEventHandler(textBox_KeyPress);  
  43.                     }  
  44.                     else  
  45.                     {  
  46.                         if(colName.DataType.MaximumLength.ToString()!="-1")  
  47.                         {  
  48.                             ctrltxt.MaxLength = Convert.ToInt32(colName.DataType.MaximumLength.ToString());  
  49.                         }  
  50.                         else  
  51.                         {  
  52.                             ctrltxt.MaxLength =100;  
  53.                         }  
  54.                     }  
  55.                       
  56.                     pnControls.Controls.Add(ctrltxt);  
  57.   
  58.                     //to add Column datatype as hidden field   
  59.                     Label ctrllbl = new Label();  
  60.                     ctrllbl.Location = new Point(lableXVal + 112, lableYVal + 6);  
  61.                     ctrllbl.Size = new Size(1, 1);  
  62.                     ctrllbl.Name = "_lblDT_" + randNumber; ;  
  63.                     ctrllbl.Font = new System.Drawing.Font("NativePrinterFontA", 7F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));  
  64.                     ctrllbl.Text = colName.DataType.Name;  
  65.                     ctrllbl.Visible = false;  
  66.                     pnControls.Controls.Add(ctrllbl);  
  67.   
  68.                     if (lableXVal + 360 < pnControls.Width-110)  
  69.                     {  
  70.                         lableXVal = lableXVal + 270;  
  71.                     }  
  72.                     else  
  73.                     {  
  74.                         lableXVal = 10;  
  75.                         lableYVal = lableYVal + 40;  
  76.                     }  
  77.                 }  
  78.             }             
  79.         }  
  80. //for numeric textbox validation  
  81.         private void textBox_KeyPress(object sender, KeyPressEventArgs e)  
  82.         {  
  83.             e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);  
  84.         }  
In SMO class loadTableColumnDetails method we will get all the column details for given database and table name return the column details as ColumnCollection top biz class for adding dynamic controls for user input to insert records. 
  1. public ColumnCollection loadTableColumnDetails(string DatabaseName,string TableName)  
  2.         {  
  3.             ColumnCollection columnDetails = null;  
  4.             try  
  5.             {  
  6.                 if (SqlServerConnect())  
  7.                 {  
  8.                     Server srv = new Server(servConn);  
  9.                     Database db = srv.Databases[DatabaseName];  
  10.                     bool tableExists = db.Tables.Contains(TableName);  
  11.                     if (tableExists)  
  12.                     {                     
  13.                         foreach (Table table in db.Tables)  
  14.                         {  
  15.                             if (table.Name == TableName)  
  16.                             {  
  17.                                 columnDetails = table.Columns;  
  18.                                 break;  
  19.                             }  
  20.                         }                         
  21.                     }     
  22.                                       
  23.                     SqlServerDisconnect();  
  24.                 }  
  25.             }  
  26.             catch (Exception ex)  
  27.             {  
  28.                 writeLogMessage(ex.Message.ToString());  
  29.             }  
  30.             return columnDetails;  
  31.         }  
Insert Records In Insert button click we pass the user added insert details panel Control with Database Name and Table Name to biz Class. In biz class we will create a dynamic Insert query with adding all the column names and add all the insert values as parameter and pass the SqlCommand to SMO Class insertQuery method for inserting new record to the given Table.
  1. public string saveTableInsertQuery(Panel pnControls, string DataBaseName, string TableName)  
  2.         {  
  3.             string result = "";  
  4.             StringBuilder sqlQuery = new StringBuilder("INSERT INTO " + TableName );  
  5.             StringBuilder Insert = new StringBuilder(" (");  
  6.             StringBuilder values = new StringBuilder("VALUES (");  
  7.             SortedDictionary<stringstring> sd = new SortedDictionary<stringstring>();  
  8.   
  9.             string columnName = "";  
  10.             string colvalue = "";  
  11.             string dataType = "";  
  12.             int iCount = 0;  
  13.   
  14.             SqlCommand command = new SqlCommand();  
  15.   
  16.             foreach (Control p in pnControls.Controls)  
  17.             {  
  18.                   
  19.                 if (p.Name.ToString().Substring(0, 4) == "lbl_")  
  20.                 {  
  21.                     columnName = p.Text;                      
  22.                 }  
  23.                 else if (p.Name.ToString().Substring(0, 4) == "txt_")  
  24.                 {  
  25.                     colvalue = p.Text;  
  26.                 }  
  27.                 else if (p.Name.ToString().Substring(0, 4) == "_lbl")  
  28.                 {  
  29.                     Insert.Append(columnName);  
  30.                     Insert.Append(", ");  
  31.   
  32.                     sd.Add(columnName, colvalue);  
  33.                     values.Append("@" + columnName);  
  34.   
  35.                     values.Append(", ");  
  36.                     if (p.Text == "int")  
  37.                     {  
  38.                         command.Parameters.Add("@" + columnName, SqlDbType.Int).Value = colvalue;  
  39.                     }  
  40.                     else if (p.Text == "varchar")  
  41.                     {  
  42.                         command.Parameters.Add("@" + columnName, SqlDbType.VarChar).Value = colvalue;  
  43.                     }  
  44.                     else if (p.Text == "nvarchar")  
  45.                     {  
  46.                         command.Parameters.Add("@" + columnName, SqlDbType.NVarChar).Value = colvalue;  
  47.                     }  
  48.                 }  
  49.             }  
  50.             string sqlresult = Insert.ToString().Remove(Insert.Length - 2) + ") ";  
  51.   
  52.             sqlQuery.Append(sqlresult);  
  53.               
  54.             string valueresult = values.ToString().Remove(values.Length - 2) + ") ";  
  55.   
  56.             sqlQuery.Append(valueresult);  
  57.             sqlQuery.Append(";");  
  58.               
  59.                 command.CommandText = sqlQuery.ToString();  
  60.                 command.CommandType = CommandType.Text;  
  61.   
  62.             return objSQL.insertQuery(DataBaseName, sqlQuery.ToString(),  command);               
  63.   
  64.         }  
Select Query In Select button click we check for select query type, if SQL Select Query check box is not checked then we will pass all the column details to biz class selectRecordsfromTableQuery Method to create a dynamic SQL Select query. If user selected all Columns then we will be using “select * from tablename”. If user checked only few columns to display then we will create a dynamic query and add all user selected columns and after that return the result as DataTable to bind in grid.
  1. public DataTable selectRecordsfromTableQuery(bool isAllColumns, CheckedListBox chkListBoxCols, string DataBaseName, string TableName)  
  2.         {  
  3.             string result = "";  
  4.             StringBuilder sqlQuery = new StringBuilder("Select * FROM " + TableName);  
  5.   
  6.             string sqlresult = sqlQuery.ToString();  
  7.             if (!isAllColumns)  
  8.             {  
  9.                 sqlQuery = new StringBuilder("Select  " );  
  10.                 foreach (object itemChecked in chkListBoxCols.CheckedItems)  
  11.                 {  
  12.                     string colsName = itemChecked.ToString();  
  13.                     sqlQuery.Append(colsName+", ");  
  14.                 }  
  15.                 sqlresult = sqlQuery.ToString().Remove(sqlQuery.Length - 2) + " FROM " + TableName;  
  16.             }         
  17.   
  18.             SqlCommand command = new SqlCommand();  
  19.             command.CommandText = sqlresult;  
  20.             command.CommandType = CommandType.Text;  
  21.   
  22.             return objSQL.selectRecordsfromTableQuery(DataBaseName, command);  
  23.   
  24.         }  
Points of Interest Hope you all liked this article. The main aim of creating this tool is for easy learning of SQL Server. Without writing SQL Script now members can connect to SQL Server, create Database, Table, Insert and select records. There are some limitations in this tool like we can add only 3 datatype for now, etc. There is no limitation for our expectation, now the code and Tool is in your hand you can add any number of functionality as per you need.

Sunday, 27 December 2015

SQL SERVER – Script: Remove Spaces in Column Name in All Tables


I have written the script and share with him.
SELECT 'EXEC SP_RENAME ''' + B.NAME + '.' + A.NAME
+ ''', ''' + REPLACE(A.NAME, ' ', '')
+
''', ''COLUMN'''
FROM   sys.columns A
INNER JOIN sys.tables B
ON A.OBJECT_ID = B.OBJECT_ID
AND OBJECTPROPERTY(b.OBJECT_ID, N'IsUserTable') = 1
WHERE  system_type_id IN (SELECT system_type_id
FROM   sys.types)
AND
CHARINDEX(' ', a.NAME) <> 0
Above script would NOT make the change, but provide a script which can be verified before executing. This is a good practice to verify the objects and scripts rather than executing it directly. Here is the test run of the script. I have created database and a few tables which have space between columns.
CREATE DATABASE SpaceRemoveDB
GO
USE SpaceRemoveDB
GO
CREATE TABLE [dbo].[AWBuildVersion] (
[SystemInformationID] [tinyint] IDENTITY(1, 1) NOT NULL
,
[Database Version] [nvarchar](25) NOT NULL
,
[VersionDate] [datetime] NOT NULL
,
[ModifiedDate] [datetime] NOT NULL
,
[NewCOlumn] [nchar](10) NULL
,
[c2] [int] NULL
,
CONSTRAINT [PK_AWBuildVersion_SystemInformationID] PRIMARY KEY CLUSTERED ([SystemInformationID] ASC)
)
GO
CREATE TABLE [dbo].[Employee] (
[First name] [varchar](100) NULL
,
[Last Name] [varchar](100) NULL
)
ON [PRIMARY]
GO
Here is the database, table and columns in SSMS. I have highlighted the column which have spaces.
column space 01 SQL SERVER   Script: Remove Spaces in Column Name in All Tables
Now, we can run the script provided earlier to test.
column space 02 SQL SERVER   Script: Remove Spaces in Column Name in All Tables
As expected, the script is showing three columns from two tables which has space. Output can be run after verification.
Once we run below, the goal is achieved.
EXEC sp_RENAME 'AWBuildVersion.Database Version', 'DatabaseVersion', 'COLUMN'
EXEC sp_RENAME 'Employee.First name', 'Firstname', 'COLUMN'
EXEC sp_RENAME 'Employee.Last Name', 'LastName', 'COLUMN'
We would get below warning three times (one for each sp_rename)
Caution: Changing any part of an object name could break scripts and stored procedures.
And here is the SSMS after running script.
column space 03 SQL SERVER   Script: Remove Spaces in Column Name in All Tables
Do you have a similar script to share with other blog readers? I think we can surely learn from each other here too.

Friday, 18 December 2015

ASP.NET MVC: Custom Validation by DataAnnotation with client side

You could write a custom validation attribute:
public class CombinedMinLengthAttribute: ValidationAttribute
{
    public CombinedMinLengthAttribute(int minLength, params string[] propertyNames)
    {
        this.PropertyNames = propertyNames;
        this.MinLength = minLength;
    }

    public string[] PropertyNames { get; private set; }
    public int MinLength { get; private set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var properties = this.PropertyNames.Select(validationContext.ObjectType.GetProperty);
        var values = properties.Select(p => p.GetValue(validationContext.ObjectInstance, null)).OfType<string>();
        var totalLength = values.Sum(x => x.Length) + Convert.ToString(value).Length;
        if (totalLength < this.MinLength)
        {
            return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }
}
and then you might have a view model and decorate one of its properties with it:
public class MyViewModel
{
    [CombinedMinLength(20, "Bar", "Baz", ErrorMessage = "The combined minimum length of the Foo, Bar and Baz properties should be longer than 20")]
    public string Foo { get; set; }
    public string Bar { get; set; }
    public string Baz { get; set; }
}
 
 
 
client side
---------------
 
 


<script src="@Url.Content("~/Scripts/jquery-1.8.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>



<script type="text/javascript">
    // we add a custom jquery validation method
    jQuery.validator.addMethod('greaterThan', function (value, element, params) {
        if (!/Invalid|NaN/.test(new Date(value))) {
            return new Date(value) > new Date($(params).val());
        }
        return isNaN(value) && isNaN($(params).val()) || (parseFloat(value) > parseFloat($(params).val()));
    }, '');

    // and an unobtrusive adapter
    jQuery.validator.unobtrusive.adapters.add('futuredate', {}, function (options) {
        options.rules['greaterThan'] = true;
        options.messages['greaterThan'] = options.message;
    });

   
    $.validator.addMethod("exclude", function (value, element, exclude) {
        if (value) {
            for (var i = 0; i < exclude.length; i++) {
                if (jQuery.inArray(exclude[i], value) != -1) {
                    return false;
                }
            }
        }
        return true;
    });

    $.validator.unobtrusive.adapters.addSingleVal("exclude", "chars");

</script>
  public class custome
    {
        [CombinedMinLengthAttribute("name ", ErrorMessage="fdgd")]
        public string name { get; set; }
        public string address { get; set; }
        [FutureDate(ErrorMessage = "Should be in the future")]
        public DateTime Date { get; set; }
    }
public class FutureDateAttribute : ValidationAttribute, IClientValidatable
    {
        public override bool IsValid(object value)
        {
            if (value == null || (DateTime)value < DateTime.Now)
                return false;

            return true;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            yield return new ModelClientValidationRule
            {
                ErrorMessage = this.ErrorMessage,
                ValidationType = "futuredate"
            };
        }
    } 
 
 

MVC 4: Custom Validation Data Annotation Attribute

Data Annotations
Validation in MVC can be done using Data Annotations that are applied to both the client and server side.

Data Annotation attributes are used to validate the user inputs when posting the form. All the Data Annotation attributes like Required, Range are derived from the ValidationAttribute class that is an abstract class. The ValidationAttribute base class lives in the System.ComponentModel.DataAnnotations namespace.

This article is showing how to create a custom Data Annotations step by step:
    Step 1
    Create a New MVC 4 Application.

    Step 2
    Select Razor View Engine.

    Step 3
    Here I am showing Email validation on the Employee Registration Form.

    Select the Model Folder then select Add New Item -> Add New Class CustomEmailValidator.cs.

    Here we need to inherit the ValidationAttribute and need to override the IsValid method.

    CustomEmailValidator.cs
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Web;  
    5. using System.ComponentModel.DataAnnotations;  
    6. using System.Text.RegularExpressions;  
    7.   
    8. namespace Custom_DataAnnotation_Attribute.Models  
    9. {  
    10.     public class CustomEmailValidator : ValidationAttribute  
    11.     {  
    12.         protected override ValidationResult IsValid(object value, ValidationContext validationContext)  
    13.         {  
    14.             if (value != null)  
    15.             {  
    16.                 string email = value.ToString();  
    17.   
    18.                 if (Regex.IsMatch(email, @"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", RegexOptions.IgnoreCase))  
    19.                 {  
    20.                     return ValidationResult.Success;  
    21.                 }  
    22.                 else  
    23.                 {  
    24.                     return new ValidationResult("Please Enter a Valid Email.");  
    25.                 }  
    26.             }  
    27.             else  
    28.             {  
    29.                 return new ValidationResult("" + validationContext.DisplayName + " is required");  
    30.             }  
    31.         }  
    32.       
    Step 4
    Right-click on the Model Folder then select Add New Item -> Add New Class -> EmployeeModel.cs.
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Web;  
    5. using System.ComponentModel.DataAnnotations;  
    6.   
    7. namespace Custom_DataAnnotation_Attribute.Models  
    8. {  
    9.     public class EmployeeModel  
    10.     {  
    11.         public string Name { get; set; }  
    12.   
    13.         [CustomEmailValidator]  
    14.         public string Email { get; set; }  
    15.         public string Password { get; set; }  
    16.         public string Mobile { get; set; }          
    17.     }  
    18. }  
    Here you can see we are using [CustomEmailValidator] in the preceding Email.

    Step 5
    Now right-click on the Controller Folder then select Add New Controller.

    controller
                                                                                  Image 1

    Here in ManageEmployeeController I added a new Index Action.
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Web;  
    5. using System.Web.Mvc;  
    6. using Custom_DataAnnotation_Attribute.Models;  
    7.   
    8. namespace Custom_DataAnnotation_Attribute.Controllers  
    9. {  
    10.     public class ManageEmployeeController : Controller  
    11.     {  
    12.         //  
    13.         // GET: /ManageEmployee/  
    14.   
    15.         public ActionResult Index()  
    16.         {  
    17.             return View();  
    18.         }  
    19.   
    20.         [AcceptVerbs(HttpVerbs.Post)]  
    21.         public ActionResult Index(EmployeeModel model)  
    22.         {  
    23.             if (ModelState.IsValid)  
    24.             {  
    25.                 ViewBag.Name = model.Name;  
    26.                 ViewBag.Email = model.Email;  
    27.                 ViewBag.Password = model.Password;  
    28.                 ViewBag.Mobile = model.Mobile;  
    29.             }  
    30.             return View(model);  
    31.         }  
    32.   
    33.         public ActionResult Register()  
    34.         {  
    35.             return View();  
    36.         }  
    37.   
    38.     }  
    39. }  
    Step 6
    Now right-click on the Index Action then select Add View.

    view
                                                               Image 2

    Step 7
    Now the ManageEmployee's index.cshtml file will look like:
    1. @model Custom_DataAnnotation_Attribute.Models.EmployeeModel  
    2.   
    3. @{  
    4.     ViewBag.Title = "Register Employee";  
    5.        
    6. }  
    7.   
    8. <h2>Register</h2>  
    9.   
    10. @using (Html.BeginForm()) {  
    11.     @Html.ValidationSummary(true)  
    12.   
    13.     <fieldset>  
    14.         <legend>EmployeeModel</legend>  
    15.   
    16.         <div class="editor-label">  
    17.             @Html.LabelFor(model => model.Name)  
    18.         </div>  
    19.         <div class="editor-field">  
    20.             @Html.EditorFor(model => model.Name)  
    21.             @Html.ValidationMessageFor(model => model.Name)  
    22.         </div>  
    23.   
    24.         <div class="editor-label">  
    25.             @Html.LabelFor(model => model.Email)  
    26.         </div>  
    27.         <div class="editor-field">  
    28.             @Html.EditorFor(model => model.Email)  
    29.             @Html.ValidationMessageFor(model => model.Email)  
    30.         </div>  
    31.   
    32.         <div class="editor-label">  
    33.             @Html.LabelFor(model => model.Password)  
    34.         </div>  
    35.         <div class="editor-field">  
    36.             @Html.EditorFor(model => model.Password)  
    37.             @Html.ValidationMessageFor(model => model.Password)  
    38.         </div>  
    39.   
    40.         <div class="editor-label">  
    41.             @Html.LabelFor(model => model.Mobile)  
    42.         </div>  
    43.         <div class="editor-field">  
    44.             @Html.EditorFor(model => model.Mobile)  
    45.             @Html.ValidationMessageFor(model => model.Mobile)  
    46.         </div>  
    47.   
    48.         <p>  
    49.             <input type="submit" value="Create" />  
    50.         </p>  
    51.     </fieldset>  
    52. }  
    53.   
    54. <div>  
    55.     @Html.ActionLink("Back to List""Index")  
    56. </div>  
    57.   
    58. @section Scripts {  
    59.     @Scripts.Render("~/bundles/jqueryval")  
    60. }  
Now run the application:

email is require
                                                                                 Image 3

output
                                                                                    Image 4

Get all the tables on which a stored procedure depends sql server

SELECT DISTINCT
      [object_name] = SCHEMA_NAME(o.[schema_id]) + '.' + o.name
    , o.type_desc
FROM sys.dm_sql_referenced_entities ('dbo.GI_VALIDATION', 'OBJECT') d
JOIN sys.objects o ON d.referenced_id = o.[object_id]
WHERE o.[type] IN ('U', 'V')


SELECT DISTINCT p.name AS proc_name, t.name AS table_name
FROM sys.sql_dependencies d
INNER JOIN sys.procedures p ON p.object_id = d.object_id
INNER JOIN sys.tables     t ON t.object_id = d.referenced_major_id
ORDER BY proc_name, table_name

Thursday, 10 December 2015

Custom Validation Message Helper in ASP.NET MVC

Introduction
I wrote an earlier post about Creating Custom Html Helpers in ASP.NET MVC which emphasized on how we can write custom html helper extensions in ASP.NET MVC according to our need, so that we can reuse them in our complete application, instead of writing plain html in View.

The example in that article was using ActionLink, today I am going to tell how we can implement custom Validation Message helper. I wanted to modify the validation message displaying in my application so that it displays * in front of required fields and the error message in tooltip of it like,

sign up
For that, add a class in the project and add an extension method which will render our custom html that will be displayed for error message,
  1. namespace CustomValidationMessageHelper.Helpers     
  2. {    
  3.     public static class Validator     
  4.     {    
  5.         public static MvcHtmlString MyValidationMessageFor < TModel,    
  6.             TProperty > (this HtmlHelper < TModel > helper,    
  7.                 Expression < Func < TModel, TProperty >> expression)    
  8.         {    
  9.                 TagBuilder containerDivBuilder = new TagBuilder("div");    
  10.                 containerDivBuilder.AddCssClass("tip_trigger");    
  11.                 containerDivBuilder.InnerHtml = "*";    
  12.     
  13.                 TagBuilder midDivBuilder = new TagBuilder("div");    
  14.                 midDivBuilder.AddCssClass("classic");    
  15.                 midDivBuilder.AddCssClass("tip");    
  16.                 midDivBuilder.InnerHtml = helper.ValidationMessageFor(expression).ToString();    
  17.     
  18.                 containerDivBuilder.InnerHtml += midDivBuilder.ToString(TagRenderMode.Normal);    
  19.     
  20.                 return MvcHtmlString.Create(containerDivBuilder.ToString(TagRenderMode.Normal));    
  21.             }    
  22.     }    
  23. }    
and then define the following CSS in a CSS file, in my case it is site.css or you can add it in the view,
  1. .validated     
  2. {    
  3.     border - color: #DCE4EC!important;    
  4. }    
  5.     
  6. textarea, input[type = "text"], input[type = "password"],    
  7.     input[type = "datetime"],    
  8.     input[type = "datetime-local"], input[type = "date"],    
  9.     input[type = "month"],    
  10.     input[type = "time"], input[type = "week"],    
  11.     input[type = "number"], input[type = "email"],    
  12.     input[type = "url"], input[type = "search"],    
  13.     input[type = "tel"], input[type = "color"],    
  14.     .uneditable - input {    
  15.         padding: 3 px 3 px;    
  16.         border: 1 px solid# DCE4EC;    
  17.     }    
  18.     
  19. .tip     
  20. {    
  21.     background: none repeat scroll 0 0# FFFFFF;    
  22.     border: 1 px solid #808080;    
  23. border-radius: 10px;    
  24. box-shadow: 0 1px 10px rgba(32, 32, 32, 0.5);    
  25. color: red;    
  26. display: none;    
  27. font-size: 12px;    
  28. font-style: normal;    
  29. margin-left: 10px;    
  30. margin-top: -24px;    
  31. padding: 4px;    
  32. position: absolute;    
  33. z-index: 999999;    
  34. }    
  35.     
  36. .tip_trigger     
  37. {    
  38. width: 10px;    
  39. float: right;    
  40. color: red;    
  41. margin-left: 3px;    
  42. }    
Now we have to add client side code, which I have written in jQuery in a js file or directly in view. In my case, I have it in CustomValidation.js file,
  1. $(document).ready(function()    
  2.   {    
  3.     //Tooltips    
  4.     var tip;    
  5.     $(".tip_trigger").hover(function()     
  6.         {    
  7.         console.log("hovered");    
  8.         tip = $(this).find('.tip');    
  9.         console.log($(this).find('.tip').find('span').html())    
  10.         if ($(this).find('.tip').find('span').html() != '')    
  11.         {    
  12.             $(this).find('.tip').show(); //Show tooltip    
  13.         }    
  14.     }, function()     
  15.      {    
  16.         $(this).find('.tip').hide(); //Hide tooltip     
  17.     });    
  18.     
  19.     ////Required fields    
  20.     $('input').each(function()    
  21.         {    
  22.         var req = $(this).attr('data-val-required');    
  23.         if (undefined != req) {    
  24.             $(this).css("border-color""#DA9BA2")    
  25.     
  26.         }    
  27.         if ($(this).val() != '')     
  28.         {    
  29.     
  30.             $(this).addClass("validated");    
  31.         }    
  32.     });    
  33.     
  34.     $('input').blur(function()    
  35.         {    
  36.     
  37.         if ($(this).val() != '')     
  38.         {    
  39.     
  40.             $(this).addClass("validated");    
  41.         } else {    
  42.     
  43.             $(this).css("border-color""#DA9BA2")    
  44.         }    
  45.     });    
  46. });   
Now in the View, add the reference to the related js and css files in the head section of View:
  1. <link href="@Url.Content(" ~/Content/site.css ")" rel="stylesheet" />    
  2. <script src="@Url.Content(" ~/Scripts/jquery-1.9.1.js ")"></script>    
  3. <script src="@Url.Content(" ~/Scripts/jquery.unobtrusive-ajax.js ")"></script>    
  4. <script src="@Url.Content(" ~/Scripts/jquery.validate.js ")" type="text/javascript"></script>    
  5. <script src="@Url.Content(" ~/Scripts/jquery.validate.unobtrusive.js ")" type="text/javascript">    
  6. </script>    
  7. <script src="@Url.Content(" ~/Scripts/CustomValidation.js ")" type="text/javascript"></script>   
Now in your view, add using statement of the namespace and now you can access the Helper method in the View,
  1. @model CustomValidationMessageHelper.ViewModels.SignUpViewModel    
  2. @using CustomValidationMessageHelper.Helpers    
  3. @ {    
  4.     Layout = null;    
  5. }    
  6.     
  7. @Html.TextBoxFor(model => model.FirstName, new    
  8. {    
  9.     @class = "form-control input-sm"    
  10. })    
  11. @Html.MyValidationMessageFor(model => model.FirstName)    
The sample project can be downloaded from here.

Monday, 2 November 2015

Using Dynamic SQL in Stored Procedures--select query by filter condition using if

Dynamic SQL allows stored procedures to “write” or dynamically generate their SQL statements. The most common use case for dynamic SQL is stored procedures with optional parameters in the WHERE clause. These are typically called from reports or screens that have multiple, optional search criteria. This article describes how to write these types of stored procedures so they execute well and resist SQL injection attacks.

A simple example of a stored procedure with dynamic SQL is:

use AdventureWorks
GO
IF  EXISTS (SELECT * FROM sys.objects
            WHERE object_id = OBJECT_ID(N'[Sales].[GetSalesOrders]')
            AND type in (N'P', N'PC'))
DROP PROCEDURE [Sales].[GetSalesOrders]
GO

CREATE PROCEDURE [Sales].[GetSalesOrders] (
    @CustomerID INT = NULL,
    @ContactID INT = NULL,
    @debug bit = 0 )
AS
SET NOCOUNT ON;

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT    @ParameterDefinition = '
    @CustomerParameter INT,
    @ContactParameter INT
';

SELECT    @SQL = N'
SELECT    [SalesOrderID], [OrderDate], [Status],
    [CustomerID], [ContactID]
FROM    [Sales].[SalesOrderHeader]
WHERE 1 = 1
';

IF @CustomerID IS NOT NULL
    SELECT @SQL = @SQL + N'
    AND CustomerID = @CustomerParameter ';
   
IF @ContactID IS NOT NULL
    SELECT @SQL = @SQL + N'
    AND ContactID = @ContactParameter ';
   
IF @debug = 1
    PRINT @SQL
   
EXEC sp_executeSQL
    @SQL,
    @ParameterDefinition,
    @CustomerParameter = @CustomerID,
    @ContactParameter = @ContactID;   
GO

EXEC [Sales].[GetSalesOrders] @debug = 1, @CustomerID = 11724


Dynamic SQL allows stored procedures to “write” or dynamically generate their SQL statements. The most common use case for dynamic SQL is stored procedures with optional parameters in the WHERE clause. These are typically called from reports or screens that have multiple, optional search criteria. This article describes how to write these types of stored procedures so they execute well and resist SQL injection attacks.
A simple example of a stored procedure with dynamic SQL is:
use AdventureWorks
GO
IF  EXISTS (SELECT * FROM sys.objects 
   WHERE object_id = OBJECT_ID(N'[Sales].[GetSalesOrders]') 
   AND type in (N'P', N'PC'))
DROP PROCEDURE [Sales].[GetSalesOrders]
GO

CREATE PROCEDURE [Sales].[GetSalesOrders] (
 @CustomerID INT = NULL,
 @ContactID INT = NULL,
 @debug bit = 0 )
AS
SET NOCOUNT ON; 

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT @ParameterDefinition = '
 @CustomerParameter INT,
 @ContactParameter INT
';

SELECT @SQL = N'
SELECT [SalesOrderID], [OrderDate], [Status], 
 [CustomerID], [ContactID]
FROM [Sales].[SalesOrderHeader]
WHERE 1 = 1
';

IF @CustomerID IS NOT NULL
 SELECT @SQL = @SQL + N'
 AND CustomerID = @CustomerParameter ';
 
IF @ContactID IS NOT NULL
 SELECT @SQL = @SQL + N'
 AND ContactID = @ContactParameter ';
 
IF @debug = 1
 PRINT @SQL
 
EXEC sp_executeSQL 
 @SQL,
 @ParameterDefinition,
 @CustomerParameter = @CustomerID,
 @ContactParameter = @ContactID; 
GO

EXEC [Sales].[GetSalesOrders] @debug = 1, @CustomerID = 11724
- See more at: http://www.sqlteam.com/article/using-dynamic-sql-in-stored-procedures#sthash.Pj99nzti.dpuf
Dynamic SQL allows stored procedures to “write” or dynamically generate their SQL statements. The most common use case for dynamic SQL is stored procedures with optional parameters in the WHERE clause. These are typically called from reports or screens that have multiple, optional search criteria. This article describes how to write these types of stored procedures so they execute well and resist SQL injection attacks.
A simple example of a stored procedure with dynamic SQL is:
use AdventureWorks
GO
IF  EXISTS (SELECT * FROM sys.objects 
   WHERE object_id = OBJECT_ID(N'[Sales].[GetSalesOrders]') 
   AND type in (N'P', N'PC'))
DROP PROCEDURE [Sales].[GetSalesOrders]
GO

CREATE PROCEDURE [Sales].[GetSalesOrders] (
 @CustomerID INT = NULL,
 @ContactID INT = NULL,
 @debug bit = 0 )
AS
SET NOCOUNT ON; 

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT @ParameterDefinition = '
 @CustomerParameter INT,
 @ContactParameter INT
';

SELECT @SQL = N'
SELECT [SalesOrderID], [OrderDate], [Status], 
 [CustomerID], [ContactID]
FROM [Sales].[SalesOrderHeader]
WHERE 1 = 1
';

IF @CustomerID IS NOT NULL
 SELECT @SQL = @SQL + N'
 AND CustomerID = @CustomerParameter ';
 
IF @ContactID IS NOT NULL
 SELECT @SQL = @SQL + N'
 AND ContactID = @ContactParameter ';
 
IF @debug = 1
 PRINT @SQL
 
EXEC sp_executeSQL 
 @SQL,
 @ParameterDefinition,
 @CustomerParameter = @CustomerID,
 @ContactParameter = @ContactID; 
GO

EXEC [Sales].[GetSalesOrders] @debug = 1, @CustomerID = 11724
- See more at: http://www.sqlteam.com/article/using-dynamic-sql-in-stored-procedures#sthash.Pj99nzti.dpuf
use AdventureWorks GO IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Sales].[GetSalesOrders]') AND type in (N'P', N'PC')) DROP PROCEDURE [Sales].[GetSalesOrders] GO CREATE PROCEDURE [Sales].[GetSalesOrders] ( @CustomerID INT = NULL, @ContactID INT = NULL, @debug bit = 0 ) AS SET NOCOUNT ON; DECLARE @SQL NVARCHAR(4000); DECLARE @ParameterDefinition NVARCHAR(4000); SELECT @ParameterDefinition = ' @CustomerParameter INT, @ContactParameter INT '; SELECT @SQL = N' SELECT [SalesOrderID], [OrderDate], [Status], [CustomerID], [ContactID] FROM [Sales].[SalesOrderHeader] WHERE 1 = 1 '; IF @CustomerID IS NOT NULL SELECT @SQL = @SQL + N' AND CustomerID = @CustomerParameter '; IF @ContactID IS NOT NULL SELECT @SQL = @SQL + N' AND ContactID = @ContactParameter '; IF @debug = 1 PRINT @SQL EXEC sp_executeSQL @SQL, @ParameterDefinition, @CustomerParameter = @CustomerID, @ContactParameter = @ContactID; GO EXEC [Sales].[GetSalesOrders] @debug = 1, @CustomerID = 11724 - See more at: http://www.sqlteam.com/article/using-dynamic-sql-in-stored-procedures#sthash.Pj99nzti.dpuf
use AdventureWorks GO IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Sales].[GetSalesOrders]') AND type in (N'P', N'PC')) DROP PROCEDURE [Sales].[GetSalesOrders] GO CREATE PROCEDURE [Sales].[GetSalesOrders] ( @CustomerID INT = NULL, @ContactID INT = NULL, @debug bit = 0 ) AS SET NOCOUNT ON; DECLARE @SQL NVARCHAR(4000); DECLARE @ParameterDefinition NVARCHAR(4000); SELECT @ParameterDefinition = ' @CustomerParameter INT, @ContactParameter INT '; SELECT @SQL = N' SELECT [SalesOrderID], [OrderDate], [Status], [CustomerID], [ContactID] FROM [Sales].[SalesOrderHeader] WHERE 1 = 1 '; IF @CustomerID IS NOT NULL SELECT @SQL = @SQL + N' AND CustomerID = @CustomerParameter '; IF @ContactID IS NOT NULL SELECT @SQL = @SQL + N' AND ContactID = @ContactParameter '; IF @debug = 1 PRINT @SQL EXEC sp_executeSQL @SQL, @ParameterDefinition, @CustomerParameter = @CustomerID, @ContactParameter = @ContactID; GO EXEC [Sales].[GetSalesOrders] @debug = 1, @CustomerID = 11724 - See more at: http://www.sqlteam.com/article/using-dynamic-sql-in-stored-procedures#sthash.Pj99nzti.dpuf
use AdventureWorks GO IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Sales].[GetSalesOrders]') AND type in (N'P', N'PC')) DROP PROCEDURE [Sales].[GetSalesOrders] GO CREATE PROCEDURE [Sales].[GetSalesOrders] ( @CustomerID INT = NULL, @ContactID INT = NULL, @debug bit = 0 ) AS SET NOCOUNT ON; DECLARE @SQL NVARCHAR(4000); DECLARE @ParameterDefinition NVARCHAR(4000); SELECT @ParameterDefinition = ' @CustomerParameter INT, @ContactParameter INT '; SELECT @SQL = N' SELECT [SalesOrderID], [OrderDate], [Status], [CustomerID], [ContactID] FROM [Sales].[SalesOrderHeader] WHERE 1 = 1 '; IF @CustomerID IS NOT NULL SELECT @SQL = @SQL + N' AND CustomerID = @CustomerParameter '; IF @ContactID IS NOT NULL SELECT @SQL = @SQL + N' AND ContactID = @ContactParameter '; IF @debug = 1 PRINT @SQL EXEC sp_executeSQL @SQL, @ParameterDefinition, @CustomerParameter = @CustomerID, @ContactParameter = @ContactID; GO EXEC [Sales].[GetSalesOrders] @debug = 1, @CustomerID = 11724 - See more at: http://www.sqlteam.com/article/using-dynamic-sql-in-stored-procedures#sthash.Pj99nzti.dpuf