using …

Pure C#

Ocak, 2009 için Arşiv

How to save data from a DataSet into a T-SQL table

Yazan: esersahin 30/01/2009

http://www.codeproject.com/KB/database/Load_DataSet_In_SQL_Table.aspx

Introduction

This article will help you understand the procedure of saving data from a DataSet into T-SQL tables. This is often required when we pull data from external resources into a DataSet and want that data to be saved in our own database.

Background

I have tried to explain the topic in detail, but a primary knowledge of C#, SQL, and XML is required to understand this article. In this article, we will do the following:

  1. Create a sample DataSet.
  2. Convert this DataSet into XML string.
  3. Send this XML string to a Stored Procedure, which will parse the XML and save the data into T-SQL tables.
  4. Analyse the T-SQL procedure which will perform step 3.

Create Sample Data

The SQL script for creating the SampleData table is given below. This script will create an empty table.

Collapse
CREATE TABLE SampleData
(
 [Name]  varchar(50) NOT NULL,
 [Address] varchar(50) NOT NULL,
 [Phone]  varchar(15) NOT NULL
)

The C# code below gets the sample data into a DataSet. We create three different columns named Name, Address, and Phone for the DataTable.

Collapse
/// <summary>
/// This method is used to populate sample data.
/// Instead of this method, you can call a method which will
/// populate data from external data sources.
/// </summary>
/// <returns>DataSet with a sample data.</returns>
private static DataSet GetDataSet()
{
    DataSet ds = new DataSet();
    DataTable dt = new DataTable("Table");

    dt.Columns.Add("Name", Type.GetType("System.String"));
    dt.Columns.Add("Address", Type.GetType("System.String"));
    dt.Columns.Add("Phone", Type.GetType("System.String"));

    DataRow dr = dt.NewRow();
    dr["Name"] = "Sandeep Aparajit";
    dr["Address"] = "Redmond USA";
    dr["Phone"] = "425-000-0000";
    dt.Rows.Add(dr);

    dr = dt.NewRow();
    dr["Name"] = "Anthony Gill";
    dr["Address"] = "Ohio USA";
    dr["Phone    "] = "625-000-0000";
    dt.Rows.Add(dr);

    ds.Tables.Add(dt);
    return ds    ;
}

Convert the DataTable (DataSet) into XML String

This is an important step. Here, we will actually convert the DataTable into its equivalent XML string. We make use of the DataSet.WriteXML() method for getting the XML string out of the DataSet.

Collapse
/// <summary>
/// This method will convert the supplied DataTable 
/// to XML string.
/// </summary>
/// <param name="dtBuildSQL">DataTable to be converted.</param>
/// <returns>XML string format of the DataTable.</returns>
private static string ConvertDataTableToXML(DataTable dtData)
{
    DataSet dsData = new DataSet();
    StringBuilder sbSQL;
    StringWriter swSQL;
    string XMLformat;
    try
    {
        sbSQL = new StringBuilder();
        swSQL = new StringWriter(sbSQL);
        dsData.Merge(dtData, true, MissingSchemaAction.AddWithKey);
        dsData.Tables[0].TableName = "SampleDataTable";
        foreach (DataColumn col in dsData.Tables[0].Columns)
        {
            col.ColumnMapping = MappingType.Attribute;
        }
        dsData.WriteXml(swSQL, XmlWriteMode.WriteSchema);
        XMLformat = sbSQL.ToString();
        return XMLformat;
    }
    catch (Exception sysException)
    {
        throw sysException;
    }
}

The Main Method

Here is the Main method, which will invoke the above mentioned methods for the conversion. Once the conversion of the DataSet to XML string is done, we will call the sp_InsertData Stored Procedure and pass this XML string as a parameter. This Stored Procedure is responsible for parsing the XML and inserting the data into the T-SQL table.

Collapse
static void Main(string[] args)
{
    // Get the sample data into DataSet.
    DataSet dsData = GetDataSet();

    // Get the XML format of the data set.
    String xmlData = ConvertDataTableToXML(dsData.Tables[0]);

    // Create a SQLConnection object.
    // TODO: Specify the correct connection string as on you computer.
    SqlConnection conn = new SqlConnection
    ("Data Source=.;Initial Catalog=DBName;Integrated Security=SSPI;");

    // Create the SQlCommand object which will be used to insert the data
    // into T-SQL tables.
    SqlCommand command = new SqlCommand
    ("sp_InsertData '" + xmlData + "'", conn);

    // Open the SQL Connection.
    conn.Open();

    // Execute the stored procedure mentioned above .
    command.ExecuteNonQuery();

    // Close the SQL Connection.
    conn.Close();
}

Stored Procedure: Sp_InsertData

The Stored Procedure sp_InsertData is the heart of this operation, since it parses the XML string and inserts the data into the T-SQL table.

Collapse
/******************************************************************************
* Stored Procedure : sp_InsertData
* Author : Sandeep Aparajit
* Description : This stored procedure will accept the data as
* an XML data table. It will parse the data table and will
* insert the data into the SampleData table.
* Date : 05 Nov 08
* Revision :
******************************************************************************/
CREATE PROCEDURE sp_InsertData
(@xmlString VARCHAR(MAX))
AS
BEGIN
    /* Initialize a handle for the XmlDocument */
    DECLARE @xmlHandle INT 

    /*
    Create a table variable to store the extract XmlData into Relational
    Database Format. Unlike temporary tables, Table variables are
    automatically removed from memory by SQL Server when the procedure
    has completed. So, there is no need to try and drop them at the
    end of the procedure.
    */
    DECLARE @stagingTable TABLE
    (
        [Name] VARCHAR(50),
        [Address] VARCHAR(50),
        [Phone] VARCHAR(50)
    ) 

    /*
    Create the XmlDocument using the handle above and the Xml
    string as parameters. If your stored procedure has an varchar input
    parameter named @xmlString, it would look like this instead:
    EXEC sp_xml_preparedocument @xmlHandle output,@xmlString
    */
    EXEC sp_xml_preparedocument @xmlHandle output, @xmlString 

    /*
    Use the OPENXML method to query the XmlDocument starting at
    /NewDataSet/SampleDataTable node.
    */
    INSERT INTO @stagingTable
    SELECT   [Name] ,
        [Address],
        [Phone]
    FROM OPENXML (@xmlHandle, '/NewDataSet/SampleDataTable',1)
        WITH ([Name] varchar(50) '@Name',
            [Address] varchar(50) '@Address',
            [Phone] varchar(50) '@Phone'
             )

    /*Insert the records into the table variable turning the XML structured
    data into relational data. We are now free to query the table variable
    just as if it were a regular table for use with data manipulation, cursors, etc...
    It could also be used for generated reports and counts in ways that might
    be simpler to code in SQL Server vs XSL.*/
    INSERT INTO SampleData ([Name],
            [Address],
            [Phone])
    (SELECT [Name] ,
        [Address],
        [Phone]
    FROM @stagingTable)

    /* Remove the document from memory */
    EXEC sp_xml_removedocument @xmlHandle
END

Yazı kategorisi: DataReader, DataSet, DataTable, XML | » yorum bırak;

Convert DataReader to Dataset (C#)

Yazan: esersahin 30/01/2009

http://netindonesia.net/blogs/rahmat.faisal/pages/10093.aspx

public static DataSet convertDataReaderToDataSet(SqlDataReader reader)
{
DataSet dataSet = new DataSet();
do
{
// Create new data table

DataTable schemaTable = reader.GetSchemaTable();
DataTable dataTable = new DataTable();

if ( schemaTable != null )
{
// A query returning records was executed

for ( int i = 0; i < schemaTable.Rows.Count; i++ )
{
DataRow dataRow = schemaTable.Rows[ i ];
// Create a column name that is unique in the data table
string columnName = ( string )dataRow[ "ColumnName" ]; //+ “<C” + i + “/>”;
// Add the column definition to the data table
DataColumn column = new DataColumn( columnName, ( Type )dataRow[ "DataType" ] );
dataTable.Columns.Add( column );
}

dataSet.Tables.Add( dataTable );

// Fill the data table we just created

while ( reader.Read() )
{
DataRow dataRow = dataTable.NewRow();

for ( int i = 0; i < reader.FieldCount; i++ )
dataRow[ i ] = reader.GetValue( i );

dataTable.Rows.Add( dataRow );
}
}
else
{
// No records were returned

DataColumn column = new DataColumn(“RowsAffected”);
dataTable.Columns.Add(column);
dataSet.Tables.Add( dataTable );
DataRow dataRow = dataTable.NewRow();
dataRow[0] = reader.RecordsAffected;
dataTable.Rows.Add( dataRow );
}
}
while ( reader.NextResult() );
return dataSet;
}

Yazı kategorisi: DataReader, DataSet, DataTable | » yorum bırak;

DataTable Relational Operators in C# – DIFFERENCE Method

Yazan: esersahin 30/01/2009

http://weblogs.sqlteam.com/davidm/archive/2004/01/19/739.aspx

The DIFFERENCE Method has no equivalent in TSQL.
It is also refered to as MINUS and is simply all the rows that are in the First table but not the Second.

The argument order of the method is important. That is: Difference(First, Second) != Difference(Second, First)

There is only the one signature for this method.
In summary the code works as follows:

Create new empty table
Create a DataSet and add tables.
Get a reference to all columns in both tables
Create a DataRelation
Using the DataRelation add rows with no child rows.
Return table

public static DataTable Difference(DataTable First, DataTable Second)

{

//Create Empty Table

DataTable table = new DataTable(“Difference”);

//Must use a Dataset to make use of a DataRelation object

using(DataSet ds = new DataSet())

{

//Add tables

ds.Tables.AddRange(new DataTable[]{First.Copy(),Second.Copy()});

//Get Columns for DataRelation

DataColumn[] firstcolumns  = new DataColumn[ds.Tables[0].Columns.Count];

for(int i = 0; i < firstcolumns.Length; i++)

{

firstcolumns[i] = ds.Tables[0].Columns[i];

}

DataColumn[] secondcolumns = new DataColumn[ds.Tables[1].Columns.Count];

for(int i = 0; i < secondcolumns.Length; i++)

{

secondcolumns[i] = ds.Tables[1].Columns[i];

}

//Create DataRelation

DataRelation r = new DataRelation(string.Empty,firstcolumns,secondcolumns,false);

ds.Relations.Add(r);

//Create columns for return table

for(int i = 0; i < First.Columns.Count; i++)

{

table.Columns.Add(First.Columns[i].ColumnName, First.Columns[i].DataType);

}

//If First Row not in Second, Add to return table.

table.BeginLoadData();

foreach(DataRow parentrow in ds.Tables[0].Rows)

{

DataRow[] childrows = parentrow.GetChildRows(r);

if(childrows == null || childrows.Length == 0)

table.LoadDataRow(parentrow.ItemArray,true);

}

table.EndLoadData();

}

return table;

}

Yazı kategorisi: DataTable | » yorum bırak;

Highlight the active textbox in ASP.NET Web forms

Yazan: esersahin 22/01/2009

http://www.dotnet2themax.com/showcontent.aspx?id=00fa0fd6-4970-4ddf-aa6b-335c3d1259be

When your data entry Web forms contain several textboxes, highlighting the textbox that has the input focus can significantly improve the user’s experience. This technique is especially effective if your layout doesn’t make immediately clear what the tab order sequence is. For example, if you have multiple columns of textboxes, are they ordered horizontally or vertically? With a few lines of client-side JavaScript code you can easily change the background and foreground color of the active textbox, and thus give immediate feedback about the field that receives the user input. DHTML makes it possible to change the HTML elements’ style (font, colors, position) by means of the control’s style property and its sub-properties. The following HTML code renders a textbox control that handles the onfocus client-side event to change its background and foreground colors, and the onblur event to restore the original colors when the control loses the focus:

<input name="txtFirstName" type="text"
	id="txtFirstName"
	onfocus= "this.style.backgroundColor='Yellow'; this.style.color = 'Blue';"
	onblur="this.style.backgroundColor='Window'; this.style.color='WindowText';"
/>

Let’s see how you can dynamically add highlighting support to all ASP.NET server-side controls, instead of hard-coding it manually. All controls that inherit from WebControl have an Attributes collection to which you can add one or more attributename=value pairs; at render-time these pairs are embedded in the standard HTML code that the control generates. The listing below shows the VB.NET and C# methods that dynamically build a piece of JavaScript code that changes the backcolor/forecolor to the specified colors:

Sub SetInputControlColors(ByVal ctl As _
   WebControl, ByVal backColor As Color, _
   ByVal foreColor As Color, _
   ByVal focusBackColor As Color, _
   ByVal focusForeColor As Color)

   Dim jsOnFocus As String = String.Format( _
      "this.style.backgroundColor = '{0}';" _
      & "this.style.color = '{1}';", _
      focusBackColor.Name, focusForeColor.Name)
   Dim jsOnBlur As String = String.Format( _
      "this.style.backgroundColor = '{0}';" _
      & "this.style.color = '{1}';", _
      backColor.Name, foreColor.Name)
   ctl.Attributes.Add("onfocus", jsOnFocus)
   ctl.Attributes.Add("onblur", jsOnBlur)
End Sub
void SetInputControlColors(WebControl ctl,
   Color backColor, Color foreColor,
   Color focusBackColor,  Color focusForeColor)
{
   string jsOnFocus = string.Format(
      "this.style.backgroundColor = '{0}';" +
      "this.style.color = '{1}';",
      focusBackColor.Name, focusForeColor.Name);
   string jsOnBlur = string.Format(
      "this.style.backgroundColor = '{0}';" +
      "this.style.color = '{1}';",
      backColor.Name, foreColor.Name);
   ctl.Attributes.Add("onfocus", jsOnFocus);
   ctl.Attributes.Add("onblur", jsOnBlur);
}

Using the SetInputControlColors method is trivial:

SetInputControlColors(txtFirstName, _
   SystemColors.Window, _
   SystemColors.WindowText, _
   Color.Yellow, Color.Blue)
SetInputControlColors(txtFirstName,
   SystemColors.Window,
   SystemColors.WindowText,
   Color.Yellow, Color.Blue);

Instead of manually calling SetInputControlColors for all the input controls on the form, you can use the SetAllInputControlsColors method shown below to change the onfocus/onblur styles for all the TextBox, ListBox and DropDownList controls in the form.

Sub SetAllInputControlsColors(ByVal parent As _
   Control, ByVal backColor As Color, _
   ByVal foreColor As Color, _
   ByVal focusBackColor As Color, _
   ByVal focusForeColor As Color)

   For Each ctl As Control In parent.Controls
      If TypeOf ctl Is TextBox OrElse _
         TypeOf ctl Is ListBox OrElse _
         TypeOf ctl Is DropDownList Then
         SetInputControlColors(DirectCast( _
            ctl, WebControl), _
            backColor, foreColor, _
            focusBackColor, _
            focusForeColor)
      Else
         SetAllInputControlsColors(ctl, _
            backColor, foreColor, _
            focusBackColor, _
            focusForeColor)
      End If
   Next
End Sub
void SetAllInputControlsColors(Control parent,
   Color backColor, Color foreColor,
   Color focusBackColor,  Color focusForeColor)
{
   foreach (Control ctl in parent.Controls)
   {
      if (ctl is TextBox || ctl is ListBox ||
         ctl is DropDownList)
      {
         SetInputControlColors(
            ctl as WebControl, backColor,
            foreColor, focusBackColor,
            focusForeColor);
      }
      else
      {
         SetAllInputControlsColors(ctl,
            backColor, foreColor,
            focusBackColor,
            focusForeColor);
      }
   }
}

This method is recursive and affects also the controls nested in control containers. All you need to do now is putting the following code in the handler of the Page.Load event:

SetAllInputControlsColors(Me, _
   SystemColors.Window, SystemColors.WindowText, _
   Color.Yellow, Color.Blue)
SetAllInputControlsColors(this,
   SystemColors.Window, SystemColors.WindowText,
   Color.Yellow, Color.Blue);

The figures below show the result in Internet Explorer.

Using client-side JavaScript isn’t the only technique you can adopt to change the style of the active control. In fact, the approach just described works well only if the form contains a small number of fields. When the form has many controls, the amount of JavaScript generated for each control bloats the page’s size and indirectly slows down its rendering. In such cases it is recommended that you define the normal and focus style by means of a Cascading Style Sheet (CSS) class in a separate stylesheet file, and write a shorter JavaScript code that just sets the control’s className property when the control gets or loses the focus. Say that you define the following class in a .css file:

.ActiveInputControl
{
	background-color: Red;
	color: Yellow;
	font-weight: bold;
}

You can call the SetAllInputControlsClassName method (defined at the end of the article) as shown here:

SetAllInputControlsClassName(Me, "", _
   "ActiveInputControl")
SetAllInputControlsClassName(this, "",
   "ActiveInputControl");

And the resulting HTML for a single control would be as follows:

<input name="txtFirstName" type="text" id="txtFirstName"
	onfocus="this.className = 'ActiveInputControl';"
	onblur="this.className = '';"
/>

(Notice that when the control does not have the focus it just has no specific style class, and therefore it has the default style.) Not only is this technique faster when a form contains many fields, it is also more easily maintainable, because you can later change the focus style by simply providing a different CSS, without recompiling the ASP.NET application.

Sub SetInputControlClassName(ByVal ctl As _
   WebControl, ByVal className As String, _
   ByVal focusClassName As String)
   Dim jsOnFocus As String = String.Format( _
      "this.className = '{0}';", focusClassName)
   Dim jsOnBlur As String = String.Format( _
      "this.className = '{0}';", className)
   ctl.Attributes.Add("onfocus", jsOnFocus)
   ctl.Attributes.Add("onblur", jsOnBlur)
End Sub

Sub SetAllInputControlsClassName(ByVal parent _
   As Control, ByVal className As String, _
   ByVal focusClassName As String)
   For Each ctl As Control In parent.Controls
      If TypeOf ctl Is TextBox OrElse _
         TypeOf ctl Is ListBox OrElse TypeOf
         ctl Is DropDownList Then
         SetInputControlClassName( _
            DirectCast(ctl, WebControl),_
            className, focusClassName)
      Else
         SetAllInputControlsClassName(ctl, _
            className, focusClassName)
      End If
   Next
End Sub
void SetInputControlClassName(WebControl ctl,
   string className, string focusClassName)
{
   string jsOnFocus = String.Format(
      "this.className = '{0}';", focusClassName);
   string jsOnBlur = String.Format(
      "this.className = '{0}';", className);
   ctl.Attributes.Add("onfocus", jsOnFocus);
   ctl.Attributes.Add("onblur", jsOnBlur);
}

void SetAllInputControlsClassName(Control parent,
   string className, string focusClassName)
{
   foreach (Control ctl in parent.Controls)
   {
      if (ctl is TextBox || ctl is ListBox ||
         ctl is DropDownList)
      {
         SetInputControlClassName(
            ctl as WebControl,
            className, focusClassName);
      }
      else
      {
         SetAllInputControlsClassName(ctl,
            className, focusClassName);
      }

   }
}

Marco Bellinaso - Code Architects Srl

Yazı kategorisi: Asp.Net, Css, TextBox, Web Forms | » yorum bırak;

Common Solutions for T-SQL Problems

Yazan: esersahin 18/01/2009

http://code.msdn.microsoft.com/SQLExamples

Information presented in this WIKI represents the suggestions, ideas, and opinions of Volunteer Moderators and Answerers who support the Microsoft MSDN SQL Server Forums. (Unless specifically stated otherwise, nothing should be construed to represent the official positions or opinions of Microsoft and/or its Employees.)

Please direct any additional Questions to the MSDN SQL Server Related Forums
—————————————————————————————————————————————————————–
How can I Prepare My Question to Increase the Possibility of Getting a Good Solution?
What are the Rules of Conduct expected on the Forums?
—————————————————————————————————————————————————————–

How To Examples of Selected T-SQL Programming Constructs

Data Related Queries
Alternatives To SQL Server Cursors
Audit or Bypass Trigger Execution
Control Return Results by Range
Create a Comma Delimited List from a Column in a Table
Create and Use A Numbers Table
Delete All Data From All User Tables In A Database
Exploring Recursive Common Table Expressions (CTE)
Find and/or Delete Duplicate Rows in a Table
Find First Available Timeslot for Scheduling
Find Rows of Data Between Two Dates
Find the Missing Parts of a List of Requirements
Implementation of DDL Trigger in SQL Server 2005
Increment an AlphaNumeric Value
ISNULL() vs. COALESCE()
Lock a Stored Procedure for Single Use Only
Pass and Handle a Delimited String similar to handling an Array() of Values
PIVOT Data Using T-SQL
Queries Based Upon The Absence of Data
Rank Values in Groups
Search all or partial columns without Dynamic SQL while avoiding SQL Injection
Search all or partial columns with Dynamic SQL while avoiding SQL Injection
SELECT TOP n by Group
UNPIVOT Data Using T-SQL

Maintenance Queries
Automate Backups in SQL Express
Detach All User Databases
Find Last BackUp Date Of All Databases On Your Server
Find Long Running Agent Jobs
Find the TOP n Longest Running Procedures (or Queries), Ordered by Total Impact on Server
Performing Common Maintenance Tasks in SQL Express
Transfer Logins to Another Server

Best Practices and Guidelines
Best practices , Design and Development guidelines for Microsoft SQL Server

SQL Server Maintenance
Automating Common DBA Tasks
Configuring SQL Server 2000 Notification with CDOSys
Configuring SQL Server 2005/2008 Database Mail
Log file growth in SQL Server
Monitor free space in the database files
Monitor free space on the server hard disks
Monitor the SQL Server Error Log
Monitor long running SQL Agent Jobs
Monitor failed SQL Agent Jobs
Monitor Service Status
Monitor System Event Logs
Monitor Running Process Information
Transfer Jobs and Logins using SSIS
Upgrading Steps to SQL Server 2005

SQL Server 2008
Manage unstructured data using FILESTREAM Feature in SQL Server 2008

—————————————————————————————————————————————————————–

How To Troubleshoot and Debug T-SQL Code

Troubleshoot Deadlocking in SQL Server.
Troubleshoot Deadlocking in SQL Server 2005 using Profiler.
Understanding the Anatomy of a Deadlock.
Using the SQL Server Profiler.

—————————————————————————————————————————————————————–

Writing Transact-SQL Statements Tutorial

http://msdn2.microsoft.com/en-us/library/ms365303.aspx
___________________________________________________________________________________________________________________

Yazı kategorisi: Transact-SQL | » yorum bırak;

Find the TOP n Longest Running Procedures (or Queries), Ordered by Total Impact on Server

Yazan: esersahin 18/01/2009

http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=LongRunningProcs&referringTitle=Home

Often it is useful to determine which procedures (or code) have the greatest Total Impact on the Server. Sometimes, that is determined by examining the I/O cost, sometimes by the Exectution Duration. The suggestion presented here will examine a SQL Server 2005 Server and return a list of the Procedures (or Queries) that have the greatest total impact on the Server. In this example, Total Impact is determined by examining the length of execution and the frequency of execution.

When attempting to determine how best to allocate resouces in order to tune a Server, it is sometimes assumed that finding the longest running Procedures, or Queries, and then working to tune those Procedures or Queries will have the greatest impact in performance tuning. In the example below, it is suggested that greater benefit may be gained by examining the Total Impact of Procedures or Queries, that is, BOTH execution time and frequency. For example, tuning a long running query so that execution time is shortened by 45 seconds, but only executed one time per minute, will have less Return On Investment (ROI) than shaving one second off of a query that executes 120 times per second.

SQL Server 2005 / SQL Server 2008 Solution
SELECT TOP 10
   ProcedureName    = t.text,
   ExecutionCount   = s.execution_count,
   AvgExecutionTime = isnull( s.total_elapsed_time / s.execution_count, 0 ),
   AvgWorkerTime    = s.total_worker_time / s.execution_count,
   TotalWorkerTime  = s.total_worker_time,
   MaxLogicalReads  = s.max_logical_reads,
   MaxLogicalWrites = s.max_logical_writes,
   CreationDateTime = s.creation_time,
   CallsPerSecond   = isnull( s.execution_count / datediff( second, s.creation_time, getdate()), 0 )
FROM sys.dm_exec_query_stats s
   CROSS APPLY sys.dm_exec_sql_text( s.sql_handle )  t
-- WHERE ...
ORDER BY
   s.total_elapsed_time DESC
ProcedureName ExecutionCount AvgExecutionTime AvgWorkerTime TotalWorkerTime MaxLogicalReads MaxLogicalWrites CreationDateTime CallsPerSecond
Exec Proc1 1 3723204 3596939 3596939 36249 112 2008-03-25 00:04:15.950 0
Exec Proc2 1 2512181 2389573 2389573 703 0 2008-03-24 23:59:15.980 0
Exec Proc3 1 1080008 971041 971041 443 0 2008-03-25 00:16:07.820 0
Exec Proc4 1 1032135 935483 935483 223 0 2008-03-25 00:13:55.193 0
Exec Proc5 1 955338 912818 912818 223 0 2008-03-25 00:15:06.617 0
Exec Proc6 1 946446 906498 906498 346 0 2008-03-25 00:15:33.227 0
Exec Proc7 1 635835 634566 634566 561 0 2008-03-24 23:22:00.280 0
Exec Proc8 1 481766 475023 475023 36202 105 2008-03-25 00:13:55.180 0
Exec Proc9 1 349026 343143 343143 36202 105 2008-03-25 00:15:06.600 0
Exec Proc10 1 346581 337336 337336 36202 105 2008-03-25 00:15:33.227 0

You may filter for a specific database by adding a filtering criteria in the WHERE clause, filtering for dbID in the dynamic management view sys.dm_exec_sql_text, something like this for the current database:

WHERE t.dbid = db_id()

Return to Top

___________________________________________________________________________________________________________________
Page Created By: Arnie Rowland, Apr 22, 2008

Yazı kategorisi: Stored Procedure, Transact-SQL | » yorum bırak;

How to Find Rows of Data Between Two Dates

Yazan: esersahin 18/01/2009

http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=FindDataBetweenDates&referringTitle=Home

tracks data chronologically with a date and time, is to extract portions of
that data between two time periods. A common mistake in SQL is to use
the between operator for datetime comparisons. This can lead to an issue
of double counting certain rows of data which is incorrect.

For example, from the following data:

orderid SubTotal Shipping OrderTotal OrderDate
1 100.00 0.00 100.00 2007-12-22 23:06:16.820
2 75.00 5.95 80.95 2007-12-22 23:06:59.787
3 25.00 5.95 30.95 2007-12-22 23:09:18.083
4 50.00 5.95 55.95 2007-12-22 23:13:15.120
5 50.00 5.95 55.95 2007-12-22 23:28:49.860
6 50.00 10.45 60.45 2007-12-22 23:37:44.593
7 200.00 13.70 213.70 2007-12-22 23:56:10.533
8 25.00 5.95 30.95 2007-12-23 00:00:00.000
9 50.00 5.95 55.95 2007-12-23 00:01:19.477
10 50.00 5.95 55.95 2007-12-23 00:08:43.227
Create Sample Data
-- Suppress data loading messages
SET NOCOUNT ON

-- Create Sample Data using a Table Varable
DECLARE @Orders TABLE
(Orderid int identity primary key,
 subtotal decimal(18,2),
 shipping decimal(18,2),
 Ordertotal decimal(18,2),
 Orderdate datetime)

-- Load Sample Data
INSERT INTO @Orders VALUES (100.00, 0.00, 100.00, 'Dec 22 2007 11:06:16:820PM')
INSERT INTO @Orders VALUES (75.00, 5.95, 80.95, 'Dec 22 2007 11:06:59:787PM')
INSERT INTO @Orders VALUES (25.00, 5.95, 30.95, 'Dec 22 2007 11:09:18:083PM')
INSERT INTO @Orders VALUES (50.00, 5.95, 55.95, 'Dec 22 2007 11:13:15:120PM')
INSERT INTO @Orders VALUES (50.00, 5.95, 55.95, 'Dec 22 2007 11:28:49:860PM')
INSERT INTO @Orders VALUES (50.00, 10.45, 60.45, 'Dec 22 2007 11:37:44:593PM')
INSERT INTO @Orders VALUES (200.00, 13.70, 213.70, 'Dec 22 2007 11:56:10:533PM')
INSERT INTO @Orders VALUES (25.00, 5.95, 30.95, 'Dec 23 2007 12:00:00:000AM')
INSERT INTO @Orders VALUES (50.00, 5.95, 55.95, 'Dec 23 2007 12:01:19:477AM')
INSERT INTO @Orders VALUES (50.00, 5.95, 55.95, 'Dec 23 2007 12:08:43:227AM')

Return to Top

If you want to find all the orders for 12/22/2007, there are a number of ways
to do it. At first you may consider using a BETWEEN 12/22/2007 AND 12/22/2007:

Example using BETWEEN and the same date
--Query to Retrieve Desired Data
DECLARE @Orderdate datetime
SET @Orderdate = '2007/12/22'

SELECT *
FROM @Orders
WHERE Orderdate BETWEEN @Orderdate AND @Orderdate

-- Results
Orderid  subtotal  shipping  Ordertotal   Orderdate
-------- --------- --------- ------------ -----------------------

Return to Top

Since this returns no data, you might then try to use DATEADD, and look for
rows BETWEEN 12/22/2007 AND 12/23/2007 like the example below:

Example using BETWEEN and the problem it can lead to
--Query to Retrieve Desired Data
DECLARE @Orderdate datetime
SET @Orderdate = '2007/12/22'

SELECT *
FROM @Orders
WHERE Orderdate BETWEEN @Orderdate AND DATEADD(dd, 1, @Orderdate)

-- Results
Orderid  subtotal  shipping  Ordertotal   Orderdate
-------- --------- --------- ------------ -----------------------
1        100.00    0.00      100.00       2007-12-22 23:06:16.820
2        75.00     5.95      80.95        2007-12-22 23:06:59.787
3        25.00     5.95      30.95        2007-12-22 23:09:18.083
4        50.00     5.95      55.95        2007-12-22 23:13:15.120
5        50.00     5.95      55.95        2007-12-22 23:28:49.860
6        50.00     10.45     60.45        2007-12-22 23:37:44.593
7        200.00    13.70     213.70       2007-12-22 23:56:10.533
8        25.00     5.95      30.95        2007-12-23 00:00:00.000

SET @Orderdate = '2007/12/23'

SELECT *
FROM @Orders
WHERE Orderdate BETWEEN @Orderdate AND DATEADD(dd, 1, @Orderdate)

-- Results
Orderid  subtotal  shipping  Ordertotal   Orderdate
-------- --------- --------- ------------ -----------------------
8        25.00     5.95      30.95        2007-12-23 00:00:00.000
9        50.00     5.95      55.95        2007-12-23 00:01:19.477
10       50.00     5.95      55.95        2007-12-23 00:08:43.227

Return to Top

As you can see Row #8 falls into both days for this example, and nothing is returned
for the first example. The reason for this is that when you provide a string with no
timestamp, and it is converted into a datetime datatype, it is set to the start of the day
which is midnight. In the first example, the query tells sql to look for an order exactly
at midnight only. The second query however, tells SQL to look from midnight 12/22 to
midnight 12/23, again this being the start of the day and not the end of it. In this case
you catch the order from midnight in the results for both 12/22 and 12/23.

The correct answer to this query is not to use BETWEEN, but to use the greater than or
equals operator (>=) and the less than operator (<).

Problem solved with greater than and less than
DECLARE @Orderdate datetime
SET @Orderdate = '2007/12/22'

SELECT *
FROM @Orders
WHERE Orderdate >= @Orderdate AND Orderdate < DATEADD(dd, 1, @Orderdate)

-- Results
Orderid  subtotal  shipping  Ordertotal   Orderdate
-------- --------- --------- ------------ -----------------------
1        100.00    0.00      100.00       2007-12-22 23:06:16.820
2        75.00     5.95      80.95        2007-12-22 23:06:59.787
3        25.00     5.95      30.95        2007-12-22 23:09:18.083
4        50.00     5.95      55.95        2007-12-22 23:13:15.120
5        50.00     5.95      55.95        2007-12-22 23:28:49.860
6        50.00     10.45     60.45        2007-12-22 23:37:44.593
7        200.00    13.70     213.70       2007-12-22 23:56:10.533

SET @Orderdate = '2007/12/23'

SELECT *
FROM @Orders
WHERE Orderdate >= @Orderdate AND Orderdate < DATEADD(dd, 1, @Orderdate)

-- Results
Orderid  subtotal  shipping  Ordertotal   Orderdate
-------- --------- --------- ------------ -----------------------
8        25.00     5.95      30.95        2007-12-23 00:00:00.000
9        50.00     5.95      55.95        2007-12-23 00:01:19.477
10       50.00     5.95      55.95        2007-12-23 00:08:43.227

Yazı kategorisi: Between, Date, Transact-SQL | » yorum bırak;

Find and/or Delete Duplicate Rows

Yazan: esersahin 18/01/2009

http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=DuplicateRows&referringTitle=Home

Let us see how to find and delete duplicate rows from a table which does not have a Primary Key.

Sample Table:

ID CustName Pincode
1 Jack 45454
2 Jill 43453
3 Tom 43453
4 Kathy 22343
5 David 65443
6 Kathy 22343
7 Kim 65443
8 Hoggart 33443
9 Kate 61143
10 Kim 65443

Desired Output: after removing duplicates

ID CustName Pincode
1 Jack 45454
2 Jill 43453
3 Tom 43453
4 Kathy 22343
5 David 65443
7 Kim 65443
8 Hoggart 33443
9 Kate 61143

Create Sample Data

-- Suppress data loading messages
SET NOCOUNT ON

-- Create Table
CREATE TABLE #Customers (ID integer, CustName varchar(20), Pincode int)

-- Load Sample Data in Table
INSERT INTO  #Customers VALUES (1, 'Jack',45454 )
INSERT INTO  #Customers VALUES (2, 'Jill', 43453)
INSERT INTO  #Customers VALUES (3, 'Tom', 43453)
INSERT INTO  #Customers VALUES (4, 'Kathy', 22343)
INSERT INTO  #Customers VALUES (5, 'David', 65443)
INSERT INTO  #Customers VALUES (6, 'Kathy', 22343)
INSERT INTO  #Customers VALUES (7, 'Kim', 65443)
INSERT INTO  #Customers VALUES (8, 'Hoggart', 33443)
INSERT INTO  #Customers VALUES (9, 'Kate', 61143)
INSERT INTO  #Customers VALUES (10, 'Kim', 65443)

Approach: Some questions to ask yourself before going ahead

What are the rules which qualify a row as a duplicate row in the Customers table?
Rows are qualified as duplicate rows in the Customers table if they have similar CustName and Pincode.

How do I identify duplicate rows?
Group the rows by CustName, Pincode. Rows having similar CustName and Pincode will have more than one rows in the grouping. So locate them using HAVING COUNT(*) > 1. If duplicate values are encountered, return the maximum ID for each duplicate row. Using the outer query, delete any ID returned by subquery.

SQL Server 2005 Solution

-- Find Duplicate Rows
SELECT	MAX(ID) as ID, CustName, Pincode FROM #Customers
GROUP BY CustName, Pincode
HAVING COUNT(*) > 1

-- Delete Duplicate Rows
DELETE FROM #Customers
WHERE ID IN
( SELECT	MAX(ID) FROM #Customers
GROUP BY CustName, Pincode
HAVING COUNT(*) > 1)

SQL Server 2000 Solution

-- Find Duplicate Rows
SELECT	MAX(ID) as ID, CustName, Pincode FROM #Customers
GROUP BY CustName, Pincode
HAVING COUNT(*) > 1

-- Delete Duplicate Rows
DELETE FROM #Customers
WHERE ID IN
( SELECT	MAX(ID) FROM #Customers
GROUP BY CustName, Pincode
HAVING COUNT(*) > 1)

___________________________________________________________________________________________________________________
Page Created By: Suprotim Agarwal, March 20, 2008

Last edited Apr 25 2008 at 10:54 AM by SuprotimAgarwal, version 7
function addComment_Click(control)
{
if(!Page_ClientValidate(‘AddCommentValidation’))
{
Page_BlockSubmit = false;
return;
}

CodePlex.UpdateProgress.displayPanelAndDisableControls(“Working…”,control);
AddCommentWithAjaxPostback();
}

Comments
ArnieRowland wrote  Apr 12 2008 at 5:42 PM

(This is a test comment to see if the author will be notified.)
Suprotim, will you be adding a SQL 2000 method to the Duplicate Rows page?

zuomin wrote  Apr 17 2008 at 12:09 PM

Optimize the find duplicate rows query a little bit.

SELECT MAX(ID), CustName, Pincode FROM #Customers GROUP BY CustName, Pincode
HAVING COUNT(*) > 1;

Vansha wrote  Apr 23 2008 at 9:37 AM

Another solution in a case when more than two duplicate rows occurs.

– Append third duplicate (to rows with Id=7 and Id=10) row to test data
INSERT INTO #Customers VALUES (11, ‘Kim’, 65443)

in this case row (7, ‘Kim’, 65443) and row (10, ‘Kim’, 65443) still present in the table after script runs.

– Delete All Duplicate Rows
DELETE FROM #Customers
WHERE EXISTS (
SELECT NULL
FROM #Customers c2
WHERE #Customers.CustName = c2.CustName
AND #Customers.Pincode = c2.Pincode
AND #Customers.ID > c2.Id
)

SuprotimAgarwal wrote  Apr 25 2008 at 10:52 AM

Thanks Vansha. If there are more than one duplicate rows, your suggested query could also be written like this:

SELECT * FROM #Customers cust WHERE EXISTS
(SELECT * FROM #Customers where CustName = cust.CustName and Pincode = cust.Pincode and ID < cust.ID)

DELETE cust FROM #Customers cust WHERE EXISTS
(SELECT * FROM #Customers where CustName = cust.CustName and Pincode = cust.Pincode and ID < cust.ID)

RyanRandall wrote  May 19 2008 at 2:17 AM

Another option for SQL 2005. This technique works for multiple duplicates AND when there is no way of uniquely identifying the row.

– Delete duplicate rows
; WITH a AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY CustName, Pincode
ORDER BY ID) AS RowId FROM #Customers)
DELETE FROM a WHERE RowId > 1

epikarma wrote  May 24 2008 at 2:16 AM

Maybe should be better using self join to identify and delete duplicates.
See: http://www.ugmfree.it/TipsTsql.aspx?tip=TipTsqlDeleteDuplicates

gr8tushar wrote  Nov 12 2008 at 12:48 PM

Ryan solutions looks good. It would work even if we have multiple duplicate contacts.

Yazı kategorisi: SQL, Sql Server, Transact-SQL | » yorum bırak;

Exploring Recursive Common Table Expressions (CTE)

Yazan: esersahin 18/01/2009

http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=RecursiveCTE&referringTitle=Home

A Common Table Expression(CTE) is an ANSI SQL-99 temporary result set that can be declared once and referenced multiple times in a query. It acts as a replacement for many sub-queries and thereby improves query simplicity and performance in most cases.

If you are new to CTE’s, I would recommend you to check this link http://msdn.microsoft.com/en-us/library/ms190766.aspx before you proceed ahead with Recursive CTE’s.

A recursive CTE is one in which a CTE refers to itself in the CTE definition to obtain subsets of data until the complete result set is obtained. Recursive CTE’s come in quiet handy when you need to represent hierarchical data and query against it. Infact, the raw power of a CTE is realized when it is used recursively to obtain a resultset. In previous versions of SQL Server, you could create recursive queries using cursors and temporary tables.

The syntax of a recursive query would be similar to the following:

WITH cte-nm (column1, column2, …)
AS
(
cte-query-definition — Anchor member
UNION ALL
cte-query-definition –- Recursive member which references cte_name
)
SELECT * FROM cte-nm

In this sample, we will see how to use Recursive CTE’s to find out the level of a team member in a project.

Case Scenario : Let us assume that we have a table called ProjectMemberDetails. We need to display the ‘Level’ of each TeamMember in that project. The level of each team member will be ascertained by the hierarchy of Managers above the person.

For the sake of demonstrating Recursive CTE’s, we will create the following columns in the ProjectMemberDetails table – ID, TeamMemNm, Designation and ManagerID. Using Recursive CTE’s, we will then calculate the level of each team member in the team. Level 1 is the highest grade, given only to those who do not have managers above them; in our case the EngagementManager.

The hierarchy of a project team for demonstratation purposes is as follows:

EngagementManager – 1
Sr. Project Manager – 2
Project Manager – 3
Project Leader – 4
Team Leader – 5
Sr. Developer – 6
Developer/Tester – 7

The code to display the hierarchy would be as follows:

SQL Server 2005/SQL Server 2008

DROP TABLE #ProjectMemberDetails
-- create temporary table called ProjectMemberDetails
CREATE TABLE #ProjectMemberDetails
(
ID int Identity(1,1) PRIMARY KEY,
TeamMemNm varchar(100),
Designation varchar(50),
ManagerID int NULL
)

-- Insert some sample records in the ProjectMemberDetails table
INSERT INTO #ProjectMemberDetails VALUES('Tim','Engagement Manager',NULL);
INSERT INTO #ProjectMemberDetails VALUES('Kathy','Sr. Project Manager',1);
INSERT INTO #ProjectMemberDetails VALUES('Levonca','Project Manager',2);
INSERT INTO #ProjectMemberDetails VALUES('Sid','Project Manager',2);
INSERT INTO #ProjectMemberDetails VALUES('Carrie','Project Leader',3);
INSERT INTO #ProjectMemberDetails VALUES('Cristina','Project Leader',4);
INSERT INTO #ProjectMemberDetails VALUES('Santi','Team Leader',5);
INSERT INTO #ProjectMemberDetails VALUES('Michelle','Team Leader',5);
INSERT INTO #ProjectMemberDetails VALUES('Pablo','Team Leader',6);
INSERT INTO #ProjectMemberDetails VALUES('Mario','Team Leader',6);
INSERT INTO #ProjectMemberDetails VALUES('Anand','Sr. Developer',7);
INSERT INTO #ProjectMemberDetails VALUES('Bill','Sr. Developer',7);
INSERT INTO #ProjectMemberDetails VALUES('Jack','Sr. Developer',8);
INSERT INTO #ProjectMemberDetails VALUES('Tibre','Sr. Developer',8);
INSERT INTO #ProjectMemberDetails VALUES('Lisa','Sr. Developer',9);
INSERT INTO #ProjectMemberDetails VALUES('Scott','Sr. Tester',10);
INSERT INTO #ProjectMemberDetails VALUES('Nancy','Developer',11);
INSERT INTO #ProjectMemberDetails VALUES('MJ','Developer',12);
INSERT INTO #ProjectMemberDetails VALUES('Ziak','Developer',13);
INSERT INTO #ProjectMemberDetails VALUES('Martin','Developer',14);
INSERT INTO #ProjectMemberDetails VALUES('David','Developer',14);
INSERT INTO #ProjectMemberDetails VALUES('Steve','Developer',15);
INSERT INTO #ProjectMemberDetails VALUES('Rachael','Developer',15);
INSERT INTO #ProjectMemberDetails VALUES('Sally','Tester',16);
INSERT INTO #ProjectMemberDetails VALUES('Peter','Tester',16);
SELECT * FROM #ProjectMemberDetails;

-- Use Recursive CTE to find out the Level of each ProjectMemberDetails
-- in the project
WITH CTE(ID, TeamMemberName, Designation, ManagerID, ProjectLevel)
AS
(
SELECT ID, TeamMemNm, Designation, ManagerID, 1 as ProjectLevel
From #ProjectMemberDetails WHERE ManagerID is NULL
UNION ALL
SELECT e.ID, e.TeamMemNm, e.Designation, e.ManagerID, c.ProjectLevel + 1
FROM #ProjectMemberDetails e
INNER JOIN CTE c
ON e.ManagerID = c.ID
)
SELECT ID, TeamMemberName, Designation, ManagerID, ProjectLevel
FROM CTE Order BY ID

Here’s a break up of the query:

1. In the query below, the anchor member returns the person who is at the highest level in the project (Engagement Manager) and marks the level as 1

SELECT ID, TeamMemNm, Designation, ManagerID, 1 as ProjectLevel
From #ProjectMemberDetails WHERE ManagerID is NULL

2. To determine the person directly below him (EngagementManager), a join is made between the ProjectMemberDetails table and the CTE, which helps in determining the member which is directly below the person returned by the anchor member. In our case, that would be the Project Manager.

3. With every recursive invocation, we get the output (c.ProjectLevel + 1) for the join e.ManagerID = c.ID

The final result set consists of the union of all the subsets generated by the anchor and recursive members. The result set is displayed below.

Result

ID TeamMemberName Designation ManagerID ProjectLevel
1 Tim Engagement Manager NULL 1
2 Kathy Sr. Project Manager 1 2
3 Levonca Project Manager 2 3
4 Sid Project Manager 2 3
5 Carrie Project Leader 3 4
6 Cristina Project Leader 4 4
7 Santi Team Leader 5 5
8 Michelle Team Leader 5 5
9 Pablo Team Leader 6 5
10 Mario Team Leader 6 5
11 Anand Sr. Developer 7 6
12 Bill Sr. Developer 7 6
13 Jack Sr. Developer 8 6
14 Tibre Sr. Developer 8 6
15 Lisa Sr. Developer 9 6
16 Scott Sr. Tester 10 6
17 Nancy Developer 11 7
18 MJ Developer 12 7
19 Ziak Developer 13 7
20 Martin Developer 14 7
21 David Developer 14 7
22 Steve Developer 15 7
23 Rachael Developer 15 7
24 Sally Tester 16 7
25 Peter Tester 16 7

References: http://msdn.microsoft.com/en-us/library/ms186243.aspx

Yazı kategorisi: Common Table Expressions, Recursive | » yorum bırak;

Lock a Stored Procedure for Single Use Only

Yazan: esersahin 18/01/2009

http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=GetAppLock&referringTitle=Home

There can, in some situations, be a need to restrict the use of a block of T-SQL code to Single Use Only. The desire may be to control for, or prevent, some concurrency issues. Perhaps incrementing a numbers table, starting a mulitiple step operation that requires that all steps be completed for a user before another user is even allowed to start, or in some decision making or process control situations.

The solution presented here will work in SQL Server 2005 / SQL Server 2008, as well as SQL Server 2000.
This demonstration requires the Northwind database.

By using a couple of system procedures, sp_getapplock and sp_releaseapplock, it is possible to register a lock, and then by checking to verify if the lock is in use, it is possible to permit or prohibit executing code appropriately.

Create a Custom Error Message, Designating an User assigned Error Number, starting at 50000, or higher, and a user designated Error Message.
USE Northwind
GO

EXECUTE sp_addmessage
   @msgnum   = 51001,
   @severity = 16,
   @msgtext  = N'Resource NOT Available',
   @lang     = 'us_english',
   @replace  = REPLACE

Return to Top

Create a Stored Procedure that Can be ‘locked’
CREATE PROCEDURE dbo.Employees_U_LastName
   (  @EmployeeID   int,
      @LastName     varchar(20)
   )
AS
   BEGIN

      SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
      BEGIN TRANSACTION

      DECLARE @LockResult int

      EXECUTE @LockResult = sp_getapplock
         @Resource    = 'RepeatableRead_TRANSACTION',
         @LockMode    = 'Exclusive',
         @LockTimeout = 0

         IF @LockResult <> 0
            BEGIN
               ROLLBACK TRANSACTION
               RAISERROR ( 51001, 16, 1 )
               RETURN
            END

         -- All code between the use of sp_getapplock above,
         -- and sp_releaseapplock below will be restricted to
         -- only one user at a time.

         -- Ten Second delay for Demonstration Purposes
         WAITFOR DELAY '00:00:10'
         -- Remove these three lines for 'Normal' use

         UPDATE Employees
            SET LastName = @LastName
            WHERE EmployeeID = @EmployeeID

         EXECUTE sp_releaseapplock
            @Resource = 'RepeatableRead_TRANSACTION'

      COMMIT TRANSACTION

   END

GO

Return to Top

Demonstration

Open two separate Query Windows, and place the following code in one of the windows.
DO NOT Execute the code until both Query Windows are in place and connected to the database.

Query Window 1
   EXECUTE dbo.Employees_U_LastName
      @EmployeeID = 1,
      @LastName   = 'Davolio-Jones'

      SELECT
         EmployeeID,
         LastName,
         FirstName
      FROM Employees
      WHERE EmployeeID = 1

Place the following code in Query window 2

Query Window 2
   EXECUTE dbo.Employees_U_LastName
      @EmployeeID = 1,
      @LastName   = 'Davolio'

      SELECT
         EmployeeID,
         LastName,
         FirstName
      FROM Employees
      WHERE EmployeeID = 1

Execute the code in Query window 1, and then immediately execute the code in Query window 2.

Results in Query Window 2
Msg 51001, Level 16, State 1, Procedure Employees_U_LastName, Line 21
Resource NOT Available

As you can see, it becomes possible to control code to single use only.

Return to Top

Clean up the test environment
DROP PROCEDURE dbo.Employees_U_LastName
Concurrency and Performance Considerations

Applications should capture the error, and handle appropriately, perhaps attempting to EXECUTE the query after a brief delay.

Yazı kategorisi: Lock, Stored Procedure, Transact-SQL | » yorum bırak;