SQL Server Table Fails to Update - sql

This is just driving me crazy. I have a small SQL Server 2012 table with the following columns:
id int (this is an IDENTITY column)
DateNewsletter smalldatetime
SubjectNewsletter varchar(100)
ContentHeader varchar(MAX)
ContentNewsletter varchar(MAX)
ContentFooter varchar(MAX)
NewsletterSent bit
DateSent smalldatetime
ApprovalPending bit
PriorityHigh bit
There are 583 rows in the table.
Here's the problem:
I can SELECT * with no problem
I can INSERT INTO with no problem
However, when I run the following query, everything blows up:
UPDATE tblElinesNewsletter
SET NewsletterSent = 1,
DateSent = GETDATE(),
ApprovalPending = 0
WHERE (NewsletterSent = 0)
Whenever I run the above code, I get a timeout error. The timeout error is the same if I run it from ASP.NET page or from SQL Server Management Studio.
Also, if I right-click from SSMS and choose 'Edit Top 200 Rows...', it will display the grid and let me edit. But as soon as I click away and it's performing the update, it's blowing up.
I've tried the following already:
Rebuild the index
Create a brand new table with same schema and transfer data over there
Restart the server
Go to home depot and purchase large can of spackle to fix holes in office wall (from banging my head against)
This is not a large table. It simply stores HTML for an email newsletter.
It didn't always do this, and only started about a few months ago. It worked fine before that.
Now, all of the above said, here's the kicker: it doesn't do this all the time. Sometimes it works. What noticed is that if there's a longer newsletter in the table, it seems to not work vs. if the newsletter is very short. These are simple newsletters and not too fancy, here's one right here: http://unitedafa.org/news/elines/view/?id=104169
This is pulling from the database/table that I discuss above.
This SQL Server installation is on a Windows Server 2012 box with 6 GB RAM and only runs a few websites that don't get that much traffic.
One thing I'm noticing as I'm trying to debug this, is that when I execute the SQL Server stored procedure from the ASP.NET web page, when it fails, this seems to freeze up the SQL Server and I can't run the same stored procedure in SSMS. However, once I restart the server, I can then open SSMS and execute the stored procedure. Again, though if I execute the stored procedure from the web page, it 'freezes' up the server again and I can't run any update query against that table.
Just for reference, here's the actual stored procedure that's being called from the page:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ======================================================
-- Author: Christopher Lee
-- Create date: 16-Aug-2012
-- Modify date: 16-Aug-2012
-- Description: Mark all records as Sent.
-- ======================================================
ALTER PROCEDURE [dbo].[sProc_Elines_Send_MarkComplete]
AS
BEGIN TRANSACTION
UPDATE tblElinesNewsletter
SET NewsletterSent = 1,
DateSent = GETDATE(),
ApprovalPending = 0
WHERE (NewsletterSent = 0)
COMMIT
Also, here's the CREATE TABLE script:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tblElinesNewsletter]
(
[id] [int] IDENTITY(100543,1) NOT NULL,
[DateNewsletter] [smalldatetime] NOT NULL,
[SubjectNewsletter] [varchar](100) NOT NULL,
[ContentHeader] [varchar](max) NOT NULL,
[ContentNewsletter] [varchar](max) NOT NULL,
[ContentFooter] [varchar](max) NOT NULL,
[NewsletterSent] [bit] NOT NULL,
[DateSent] [smalldatetime] NULL,
[ApprovalPending] [bit] NOT NULL,
[PriorityHigh] [bit] NOT NULL,
CONSTRAINT [PK_tblElinesNewsletter2]
PRIMARY KEY CLUSTERED ([id] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[tblElinesNewsletter]
ADD CONSTRAINT [DF_tblElinesNewsletter2_PriorityHigh] DEFAULT ((0)) FOR [PriorityHigh]
GO
Any idea what on earth I'm doing wrong? BTW, I'm not a DBA and more familiar with ASP.NET web code, etc., more than SQL statements.
Any help or advice would be appreciated!
-- Chris
PS, here's some additional info:
SQL Server Query Execution Plan on the Stored Proc:
[SQL Server Execution Plan Screenshot][1]
Here's some additional info:
There's enough hard drive space.
There's no other concurrent processes.
The stored proc is actually executed in a sequence with two other before it. Here's the code from the executing page:
Protected Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Call WriteNewsletterFile()
Call SendNewsletter()
Call UpdateRecord()
End Sub
So the WriteNewsletterFile() and the SendNewsletter() subroutines work fine. It blows up on the UpdateRecord subroutine. Here's the code for each of the routines:
Sub WriteNewsletterFile()
Dim NewsID As String = ""
Dim Conn As SqlConnection
Dim Cmd As SqlCommand
Dim Rdr As SqlDataReader
Conn = New SqlConnection(ConfigurationManager.ConnectionStrings("UnitedAFAConnectionStringNSS").ConnectionString)
Cmd = New SqlCommand()
Cmd.CommandText = "sProc_Elines_Send_GetContentPending"
Cmd.CommandType = CommandType.StoredProcedure
Cmd.Connection = Conn
Cmd.Connection.Open()
Rdr = Cmd.ExecuteReader(CommandBehavior.CloseConnection)
If Rdr.HasRows Then
While Rdr.Read
NewsID = Rdr("id")
NewsletterSubject = Rdr("SubjectNewsletter")
NewsletterHeader = Rdr("ContentHeader")
NewsletterContent = Rdr("ContentNewsletter")
NewsletterFooter = Rdr("ContentFooter")
End While
End If
Conn.Close()
Conn.Dispose()
Cmd.Dispose()
' Header
NewsletterHeaderForEmail = NewsletterHeader.Replace("<p>", "<p style=""font-family: Arial, Helvetica, sans-serif; font-size: 12pt; line-height: 1.3em;margin-bottom:1em"">")
NewsletterHeaderForEmail = NewsletterHeaderForEmail.Replace("<li>", "<li style=""font-family: Arial, Helvetica, sans-serif; font-size: 12pt; line-height: 1.3em;margin-bottom:1em"">")
NewsletterHeaderForEmail = NewsletterHeaderForEmail.Replace("[NewsID]", NewsID)
' Footer
NewsletterFooterForEmail = NewsletterFooter.Replace("<p>", "<p style=""font-family: Arial, Helvetica, sans-serif; font-size: 12pt; line-height: 1.3em;margin-bottom:1em"">")
NewsletterFooterForEmail = NewsletterFooterForEmail.Replace("<li>", "<li style=""font-family: Arial, Helvetica, sans-serif; font-size: 12pt; line-height: 1.3em;margin-bottom:1em"">")
' Content
NewsletterContentForEmail = NewsletterContent.Replace("<p>", "<p style=""font-family: Arial, Helvetica, sans-serif; font-size: 12pt; line-height: 1.3em;margin-bottom:1em"">")
NewsletterContentForEmail = NewsletterContentForEmail.Replace("<li>", "<li style=""font-family: Arial, Helvetica, sans-serif; font-size: 12pt; line-height: 1.3em;margin-bottom:1em"">")
NewsletterContentForEmail = "<table border=""0"" cellpadding=""0"" cellspacing=""0""><tr><td style=""font-family: Arial, Helvetica, sans-serif; font-size: 12pt"">" & NewsletterContentForEmail & "</td></tr></table>"
NewsletterFinalReadyForSending = NewsletterHeaderForEmail & NewsletterContentForEmail & NewsletterFooterForEmail
Dim filePath2 As String = "C:\Programs\SendElines.bat"
Dim w2 As StreamWriter
w2 = File.CreateText(filePath2)
w2.WriteLine("START """" ""C:\Program Files (x86)\Gammadyne Mailer\gm.exe"" /s /n /subject""" & NewsletterSubject & """ /html""C:\Programs\elines.html"" ""C:\Users\Public\Documents\Newsletters\Elines\Sending Template - Elines.mmp""")
w2.Flush()
w2.Close()
Dim filePath As String = "C:\Programs\elines.html"
Dim w As StreamWriter
w = File.CreateText(filePath)
w.WriteLine(NewsletterFinalReadyForSending)
w.Flush()
w.Close()
End Sub
Sub SendNewsletter()
Dim Conn As New SqlConnection(ConfigurationManager.ConnectionStrings("UnitedAFAConnectionStringAfaNewsletters").ConnectionString)
Dim MySQL As String = "sProc_SendElines"
Dim Cmd As New Data.SqlClient.SqlCommand(MySQL, Conn)
Cmd.CommandType = CommandType.StoredProcedure
Conn.Open()
Cmd.ExecuteNonQuery()
Conn.Close()
Conn.Dispose()
End Sub
Sub UpdateRecord()
Dim Conn As New SqlConnection(ConfigurationManager.ConnectionStrings("UnitedAFAConnectionStringNSS").ConnectionString)
Dim MySQL As String = "sProc_Elines_Send_MarkComplete"
Dim Cmd As New Data.SqlClient.SqlCommand(MySQL, Conn)
Cmd.CommandType = CommandType.StoredProcedure
Conn.Open()
Cmd.ExecuteNonQuery()
Conn.Close()
Conn.Dispose()
End Sub
And here's the code for the SendElines Subroutine:
USE [afanewsletters]
GO
/****** Object: StoredProcedure [dbo].[sProc_SendElines] Script Date: 9/5/2017 2:51:08 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ======================================================
-- Author: Christopher Lee
-- Create date: 21-Aug-2012
-- Modify date: 21-Aug-2012
-- Description: Runs the Elines sending BAT file.
-- ======================================================
ALTER PROCEDURE [dbo].[sProc_SendElines]
AS
EXEC xp_logevent 67845, 'Send Elines', informational
I should point out that the SendElines() stored proc is on a different database (but on same server). Again though, to be clear, the first two subroutines work fine. It's just the sProc_Elines_Send_MarkComplete that blows up.
Here's the code for sProc_Elines_Send_GetContentPending:
USE [Newsletters]
GO
/****** Object: StoredProcedure [dbo].[sProc_Elines_Send_GetContentPending] Script Date: 9/6/2017 6:57:06 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ======================================================
-- Author: Christopher Lee
-- Create date: 16-Aug-2012
-- Modify date: 16-Aug-2012
-- Description: Get content for Elines for approval.
-- ======================================================
ALTER PROCEDURE [dbo].[sProc_Elines_Send_GetContentPending]
AS
BEGIN TRY
BEGIN TRANSACTION
SELECT * FROM tblElinesNewsletter
WHERE (NewsletterSent = 0)
COMMIT
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK
RAISERROR ('Problem with sProc_Elines_Send_GetContentPending, please contact the MEC Webmaster at webmaster#unitedafa.org.', 16, 1)
END CATCH
Here's the results of the DBCC OPENTRAN I ran. The first two stored procs (sProc_Elines_Send_GetContentPending and sProc_SendElines) executed successfully. However, when sProc_Elines_Send_MarkComplete ran and hung, I ran the DBCC OPENTRAN which contained the message: "No active open transactions." Screenshot enclosed: Here's the DBCC OPENTRAN screenshot

In this code
Rdr = Cmd.ExecuteReader(CommandBehavior.CloseConnection)
If Rdr.HasRows Then
While Rdr.Read
....
End While
End If
Conn.Close()
Conn.Dispose()
you do not close and dispose the reader. I don't know the internals of SqlConnection and SqlDataReader, but an open reader may cause the conn.Close() the have no effect.
If the reader is open, this means that the records and tables read by sProc_Elines_Send_GetContentPending are probably locked, which means that the locks are not released, even though the records are not accessed any more.
You should also have a look at the Using statement (see this question) to handle connections, commands, and readers.
Further, you have a While loop, but only process a single record. And if the Reader does not return a record, you end up with a lot of uninitialized variables. But that's not related to your locking problem.

The query looks fine, and if you have less than 1k rows, I don't know why it would end up timing out.
One thing you could try is to add a variable at the top, and add CAST(GETDATE() AS smalldatetime) into that. Then use the variable in your update.
DECLARE #myDate smalldatetime AS CAST(GETDATE() AS smalldatetime)
UPDATE tblElinesNewsletter
SET
NewsletterSent = 1,
DateSent= myDate ,
ApprovalPending = 0
WHERE NewsletterSent = 0
I'm not sure it'll do anything, but the idea is to store the value of the date in a constant, rather than have it evaluated in the WHERE clause.

All:
First off, thank you for your help/assistance. This was really the first time I've used this board with such an extensive issue. I wish I could awared ALL responses, as they all helped to paint a clearer picture of what was going on.
I solved the issue in part by what Devio said about connections not being closed. Digging into the .NET page further, I found that there was a Session State database call that managed the security of the page. This was coming from an iframe tag and actually on a DIFFERENT page using the same connection string and database. Apparently this connection string did NOT close and remained open with the same database and same overall table. Then the sProc_Elines_Send_GetContentPending proc tried to run -- which it appeared to do, as did the sProc_SendElines proc. However when the sProc_Elines_Send_MarkComplete proc tried to run, it failed as I mentioned eariler.
When I rewrote the database connection code to add to following statements:
Cmd.ExecuteNonQuery()
Conn.Close()
Conn.Dispose()
It then closed the security Session State database connection, which then allowed all three of the other stored procedures to run.
So again, this resolved the issue and the genesis of figuring it out for me was from Devio's close connection suggestion.
I hope I did this question closure with the correct Stack Overflow protocol and please let me know if I missed anything. Thanks again everyone. You are the best!
-- Chris

Related

Cannot create SqlLite database on target PC - fine on dev PC

I've made a VSTO addin for outlook, and it works fine in both release and debug modes on my development machine. Even if I manually delete all the build files and the sqllite database it creates everything from scratch the next time you launch outlook, and carries on as though nothing happened.
When I then install it on the target computer, it simply won't create a sqllite database file. It'll make the directory to put it in, tell me where it's going to put it, and then it just doesn't make the file. It then can't store what it's doing later on, and so just falls over. Unfortunately I copied the command to make the connection from a tutorial, and so don't know what to try!
My code is below:
Public Class ClsSqlLiteDatabase
Public sub new ClsSqlLiteDatabase
Try
Dim sqlite_cmd As SQLiteCommand
Dim dataFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\SBDR Toolbox\"
If (Not System.IO.Directory.Exists(dataFolder)) Then
System.IO.Directory.CreateDirectory(dataFolder)
End If
Debug.WriteLine(dataFolder & "database.sqlite")
' create a new database connection:
conn = New SQLiteConnection("Data Source=" & dataFolder & "database.sqlite;Version=3;")
' open the connection:
conn.Open()
sqlite_cmd = conn.CreateCommand()
' Let the SQLiteCommand object know our SQL-Query:
sqlite_cmd.CommandText = "CREATE TABLE IF NOT EXISTS
[MyBids] (
[pReference] NVARCHAR(2048) NULL PRIMARY KEY,
[sReference] NVARCHAR(2048) NULL,
[AM] NVARCHAR(2048) NULL,
[CC] NVARCHAR(2048) NULL,
[Customer] NVARCHAR(2048) NULL,
[Vendor] NVARCHAR(2048) NULL,
[Distributor] NVARCHAR(2048) NULL,
[NDT] NVARCHAR(2048) NULL)"
' Now lets execute the SQL ;-)
sqlite_cmd.ExecuteNonQuery()
Catch
Debug.WriteLine("Could not initialise SQLLite Database")
End Try
End Sub

VB.NET upload SQL script to create database and tables

I have written a small application. On first run of the application I want to upload an SQL script to the local SQL Server Express Instance.
On my development machine I have created the database and tables and have exported the scripts using SSMS to a sql file. I can import that file into SSMS and execute it, and the database will be created. I do not know how to perform the same process using VB.NET
I added the sql file to my project as a resource and I have included the first few lines below
USE [master]
GO
/****** Object: Database [MyProject] Script Date: 5/04/2016 11:30:42 PM ******/
CREATE DATABASE [MyProject]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'MyProject', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\MyProject.mdf' , SIZE = 4160KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'MyProject_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\MyProject_log.ldf' , SIZE = 1040KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
ALTER DATABASE [MyProject] SET COMPATIBILITY_LEVEL = 110
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [MyProject].[dbo].[sp_fulltext_database] #action = 'enable'
end
GO
ALTER DATABASE [MyProject] SET ANSI_NULL_DEFAULT OFF
...
...
USE [MyProject]
GO
/****** Object: Table [dbo].[SomeTable] Script Date: 5/04/2016 11:30:42 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[SomeTable](
[Identifier] [int] IDENTITY(1,1) NOT NULL,
....
I then used the below code to upload the SQL to the database
Private Sub Create_SQL_Database()
Dim connetionString As String = "Data Source=localhost\SQLEXPRESS;Trusted_Connection=YES"
Dim cnn As SqlConnection = New SqlConnection(connetionString)
Dim cmd As SqlCommand = New SqlCommand()
Try
cnn.Open()
Console.Writeline("Connection Open ! Attempting to create database")
cmd.CommandText = My.Resources.CreateDatabaseSQL
cmd.Connection = cnn
Try
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show("Error - " & ex.Message)
End Try
This did not work and I received a lot of errors in a messagebox - Incorrect syntax near 'GO' followed by Database 'MyProject' does not exist. Make sure that the name is entered correctly.
I tried removing all of the lines containing GO but was still left with the error - Database 'MyProject' does not exist. Make sure that the name is entered correctly.
I am no expert on this matter but It would seem to me that the GO commands will commit the changes to the database. Because I have been removed the lines with GO on them when the script reaches this line
USE [MyProject]
the database does not exist because the previous steps have not been committed.
What do I need to do in VB.NET to be able to upload this file to the database and create my database and tables?
Thanks.

VBA Call to SQL Stored Procedure Causing Other Pages to hang

I've got a simple piece of code that executes a SQL Server backup.
With sCmd
.ActiveConnection = sCN
.CommandText = "dbo.csp_ad_hoc_single_full_backup"
.CommandType = adCmdStoredProc
.Parameters.Refresh
.Parameters("#database_name").Value = strDB
.Parameters("#backup_dir").Value = preBackup_directory
.Parameters("#backup_dir_space").Value = objDiskSpace
.Execute , , adAsyncExecute
End With
returnvalue = sCmd.parameters(0)
This code executes when the user hits the page, the return value then displays a different text per each possible result of the procedure.
The problem is that I cannot hit any other pages while this procedure runs. I've tried using 'adAsyncExecute', but that does not seem to work. The page that displays the results and runs this code does not load until the entire backup completes. I wonder if perhaps this is why other pages hang.
Any ideas?
As per enderland's comment, VBA will not continue until the .Execute process completes.
My solution is to simply write the parameters sql table instead of immediately trying to execute the procedure. The web page will display the table write as sucessful. A job will then pick up those parameters and execute the code as it would have upon page load originally. The user will be notified of the job's completion via email using msdb.dbo.sp_send_dbmail a the end of the job.

Stored procedure call from Access VBA interrupted with "Run the RECONFIGURE statement to install"

I have an Access ADP tied to an SQL Server 2005 backend. I'm trying to implement a stored procedure to update our clients' addresses, which requires me to execute a program from the command line using xp_cmdshell. The procedure works fine from SSMS, but when I call it from Access VBA, via an ADO Connection object, it produces the following "error":
Run-time error '-2147217900' (80040e14): Configuration option 'show
advanced options' changed from 0 to 1. Run the RECONFIGURE statement
to install.
It's not really an error -- it's a standard message SQL Server produces when executing sp_configure. The stored procedure does call RECONFIGURE, but for some reason Access interprets the message as an error.
Any idea how I can get this to stop?
For what it's worth, here's some of the code I'm using. This is a stored procedure to enable/disable xp_cmdshell:
ALTER PROCEDURE [dbo].[spEnableXpCmdShell]
(#enabled bit)
WITH EXECUTE AS 'NKA\jrosenberg'
AS
SET NOCOUNT ON
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', #enabled
RECONFIGURE
EXEC sp_configure 'show advanced options', 0
RECONFIGURE
That's called from my main sp, which is rather long, like so:
EXEC [dbo].[spEnableXpCmdShell] 1
Finally, here's a somewhat abridged version of the offending VBA code:
Public Function DoNCOA(con, Optional caseId = Null, _
Optional docId = Null) As Integer
'Call the NCOAProces stored procedure asynchronously.
'Returned integer is not success or failure, but position in the queue
On Error GoTo ErrHandler
Dim cmd As New ADODB.Command, _
prm As ADODB.Parameter
With cmd
.ActiveConnection = con
.CommandText = "spNCOAProcess"
.CommandType = adCmdStoredProc
.CommandTimeout = 1800
Set prm = .CreateParameter("CaseID", adInteger, adParamInput, , caseId)
.Parameters.Append prm
Set prm = .CreateParameter("DocID", adInteger, adParamInput, , docId)
.Parameters.Append prm
.Execute Options:=adAsyncExecute, adExecuteNoRecords
End With
[...That's all the important stuff]
End Function
Any help would be really appreciated!
How about running sp_configure within try/catch block so no message is returned to the client?
http://msdn.microsoft.com/en-us/library/ms175976(v=sql.90).aspx

Sql paramters appear to not add in the single quote for strings(commit transaction issue)

I wasn't sure exactly how to phrase the question Title.
I have this block of code that sets up my sql parameters for a stored proc that does an insert.
Dim sproc As StoredProcedure = New StoredProcedure("UsersInsert2", DataAccessConfiguration)
sproc.AddInput("#ID", SqlDbType.NVarChar, 10, entity.UserId)
sproc.AddInput("#PCode", SqlDbType.SmallInt, entity.PriviledgeCode)
sproc.AddInput("#Pwd", SqlDbType.NVarChar, 10, entity.Password.ToString())
sproc.AddInput("#Lang", SqlDbType.NVarChar, 1, entity.DefaultLanguage)
sproc.AddInput("#Name", SqlDbType.NVarChar, 40, entity.UserName)
sproc.AddInput("#Notice", SqlDbType.TinyInt, entity.SaveNotice)
sproc.AddInput("#CreatedBy", SqlDbType.VarChar, 50,CurrentUserCredentials.UserName)
I've tested the stored proc in SSMS and it works.
The problem is when I try to call it from the application. it fails. the ##rowcount = -1. I've tried returning an error code from the db... no dice. keeps coming back as -1
what is going to get executed looks like this
sproc = {EXEC UsersInsert2 #ID=ruxtest7, #PCode=0, #Pwd=1234, #Lang=E, #Name=ruxpint, #Notice=1, #CreatedBy=ruxpint}
any idea what the issue is? I've re-used this code several times. only difference being I'm using NVarChar and it's vb.net.
thanks.
TR
So turns out my stored proc call was fine. in my base class where I perform the transaction, I forgot to commit it. D'oh! (This may help someone in the future)
Try
x = command.ExecuteNonQuery()
transaction.Commit() <- I was missing this line!!!
Catch ex As Exception
transaction.Rollback()
Finally
If conn.State And ConnectionState.Closed = 0 Then
conn.Close()
End If
End Try