Error: Operation is not allowed when the object is closed - sql-server

I have the following code:
set ors1 = server.CreateObject("ADODB.recordset")
sqlString = "USE PoSystem OPEN SYMMETRIC KEY WebUsersPasswordEncryption DECRYPTION BY CERTIFICATE EncryptUsersPasswords "&_
"SELECT UserName,JobTitle,UserRoleID,FullName,EntityID,StatusID,CONVERT(nvarchar(50),DECRYPTBYKEY(Password)) AS PASSWORD,Email,BeneficiaryID,DATEADD(dd, 0, DATEDIFF(dd, 0, LastLoginDate)) AS LastLoginDate "&_
"FROM TblWebUsers WHERE UserID="&UserID&" CLOSE SYMMETRIC KEY WebUsersPasswordEncryption"
ors1.Open sqlString,conn,3,1
UserName = ors1("UserName")
Remark = ors1("JobTitle")
PassWord = ors1("PassWord")
Email = ors1("Email")
UserRoleID = ors1("UserRoleID")
StatusID = ors1("StatusID")
Entity = ors1("EntityID")
userFullName= ors1("FullName")
BeneficiaryID = ors1("BeneficiaryID")
LastLoginDate = ors1("LastLoginDate")
ors1.Close
But I'm getting the following message:
Operation is not allowed when the object closed
on ors1("UserName")
How can I solve it? I tried to add SET NOCOUNT ON but it's not working.

As #Paul mentioned in the comments, if you query doesn't return any records, you're going to get an error when you try to access the row values.
Guard against this error by testing to see if the Recordset is at the end (EOF). For example:
ors1.Open sqlString,conn,3,1
' Make sure recordset isn't empty...
If Not ors1.EOF Then
UserName = ors1("UserName")
Remark = ors1("JobTitle")
PassWord = ors1("PassWord")
...
Else
' Query returned no records
End If
If you need to process multiple records, use a loop:
ors1.Open sqlString,conn,3,1
Do Until ors1.EOF
UserName = ors1("UserName")
Remark = ors1("JobTitle")
PassWord = ors1("PassWord")
...
ors1.MoveNext
Loop

I found my problem
needed to change connection string
from:
ConnStr = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source='10.1.1.1';Initial Catalog='***';Uid=***;Pwd=*****;"
I change it to:
ConnStr="Driver={SQL Server};Server=10.1.1.1;Database=****;Uid=**;Pwd=*****;"

Related

Why does Snowflake variable binding in query throw error with table name but not integer?

I am following the Snowflake Python Connector docs for variable binding to avoid SQL injection. I successfully set up a db connection with the following dict of credentials:
import snowflake.connector
CONN = snowflake.connector.connect(
user=snowflake_creds['user'],
password=snowflake_creds['password'],
account=snowflake_creds['account'],
warehouse=snowflake_creds["warehouse"],
database=snowflake_creds['database'],
schema=snowflake_creds['schema'],
)
cur = CONN.cursor(snowflake.connector.DictCursor)
The following block works fine and I get back query results, hard-coding the table name and using the standard format binding:
command = ("SELECT * FROM TEST_INPUT_TABLE WHERE batch_id = %s")
bind_params = (2)
results = cur.execute(command % bind_params).fetchall()
Similarly, this block works fine, using the pyformat binding:
command = ("SELECT * FROM TEST_INPUT_TABLE WHERE batch_id = %(id)s")
bind_params = {"id": 2}
results = cur.execute(command, bind_params).fetchall()
But the following two blocks both result in a ProgrammingError (pasted below the second block):
command = ("SELECT * FROM %s WHERE batch_id = %s")
bind_params = ("TEST_INPUT_TABLE", 2)
results = cur.execute(command, bind_params).fetchall()
command = ("SELECT * FROM %(tablename)s WHERE batch_id = %(id)s")
bind_params = {
"tablename": "TEST_INPUT_TABLE",
"id": 2
}
results = cur.execute(command, bind_params).fetchall()
ProgrammingError: 001011 (42601): SQL compilation error:
invalid URL prefix found in: 'TEST_INPUT_TABLE'
Is there some difference between how strings and ints get interpolated? I would
not think it would make a difference but that is all I can think of. Am I
missing something simple here? I don't want to have to choose between hard-coding the table name and putting the system at risk of SQL injection. Thanks for any guidance.
You should be wrapping your bind variables with an INDENTIFER() function when they reference an object, rather than a string literal. For example:
command = ("SELECT * FROM IDENTIFIER(%(tablename)s) WHERE batch_id = %(id)s")
https://docs.snowflake.com/en/sql-reference/identifier-literal.html
Give that a try.

Change ResultSet to TYPE_SCROLL_INSENSITIVE in Scala

I'm using Scala to connect to a database. The connection is working and I can execute SQL with the output stored in a ResultSet. I now need to change the ResultSet to TYPE_SCROLL_INSENSITIVE so that I can point to specific rows in the ResultSet. This is a section of my code (connection details omitted for data privacy):
import java.sql.{Connection, ResultSet, SQLException, Statement}
object test extends App {
def connectURL (): java.sql. Connection = {
val url = "connection url"
val username = sys.env.get("USER").get
val password = sys.env.get("PASS").get
Class. forName ( "driver name" )
var connection = java.sql.DriverManager. getConnection ( url , username , password )
connection
}
val query = "SELECT * FROM TABLE1"
val con : java.sql. Connection = connectURL (); // creates the connection
val st = con . createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE); // creates connection statement
val rs = st.executeQuery(query); // executes the query and stores as ResultsSet
}
This gives the error: overloaded method value createStatement
The con variable is of type Connection, st is of type Statement and rs is of type ResultSet. I've tried changing val to the types above, and I get this error: value st is not a member of object java.sql.Statement
Any help would be much appreciated.
Please see javadocs https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html
createStatement is defined with either 0,2, or 3 parameters

Weird SQL Error (Bug)

So this is really weird.
I run a sql command from .net on sqlserver with a 'Select Count(*)' and get a response like "Needs attention CA" (which is in a varchar of one field of one record of the inner joined tables).
Huh? How can Count(*) return a string? 999 out of 1000 times this code executes correctly. Just sometimes on some clients servers it will throw a string of errors for an hour or so only to miraculously stop again.
This is my sqlcommand:
SELECT Count(*)
FROM patientsappointments
INNER JOIN appointmenttypes
ON patientsappointments.appointmenttypeid =
appointmenttypes.appointmenttypeid
WHERE ( ( patientsappointments.date > #WeekStartDate
AND patientsappointments.date < #WeekFinishDate )
AND ( patientsappointments.status = 'Pending' )
AND ( patientsappointments.doctorid = #DoctorID )
AND ( appointmenttypes.appointmentname <> 'Note' ) )
And these are the parameters:
#WeekStartDate = 24/06/2013 12:00:00 AM (DateTime)
#WeekFinishDate = 1/07/2013 12:00:00 AM (DateTime)
#DoctorID = 53630c67-3a5a-406f-901c-dbf6b6d1b20f (UniqueIdentifier)
I do a sqlcmd.executescalar to get the result. Any ideas?
The actual executed code is:
SyncLock lockRefresh
Dim WeekFulfilled, WeekPending As Integer
Using conSLDB As New SqlConnection(modLocalSettings.conSLDBConnectionString)
Dim mySQL As SqlCommand
mySQL = New SqlCommand("SELECT COUNT(*) FROM PatientsAppointments INNER JOIN AppointmentTypes ON PatientsAppointments.AppointmentTypeID = AppointmentTypes.AppointmentTypeID " & _
"WHERE ((PatientsAppointments.Date > #WeekStartDate AND PatientsAppointments.Date < #WeekFinishDate) AND (PatientsAppointments.Status = 'Pending') " & _
"AND (PatientsAppointments.DoctorID = #DoctorID) AND (AppointmentTypes.AppointmentName <> 'Note'))", conSLDB)
Try
mySQL.Parameters.Add("#WeekStartDate", SqlDbType.DateTime).Value = MonthCalendar1.SelectionStart.Date.AddDays(-MonthCalendar1.SelectionStart.Date.DayOfWeek).AddDays(1)
mySQL.Parameters.Add("#WeekFinishDate", SqlDbType.DateTime).Value = MonthCalendar1.SelectionStart.Date.AddDays(-MonthCalendar1.SelectionStart.Date.DayOfWeek).AddDays(8)
mySQL.Parameters.Add("#DoctorID", SqlDbType.UniqueIdentifier).Value = cboDoctors.SelectedValue
conSLDB.Open()
'got errors here like "Conversion from string "R2/3" to type 'Integer' is not valid." Weird.
'failing on deadlock - maybe due to simultaneous updating from udp event. Try adding random delay to refresh
WeekPending = mySQL.ExecuteScalar
Catch ex As Exception
ErrorSender.SendError("frmAppointmentBook - RefreshHeader 1", ex, New String() {String.Format("mySQL.commandtext: {0}", mySQL.CommandText), _
String.Format("mySQL.Parameters: {0}", clsErrorSender.ParamsListToString(mySQL.Parameters))})
End Try
Me.lblPendingWeek.Text = WeekPending
Try
mySQL.CommandText = "SELECT COUNT(*) FROM PatientsAppointments INNER JOIN AppointmentTypes ON PatientsAppointments.AppointmentTypeID = AppointmentTypes.AppointmentTypeID WHERE " & _
"(PatientsAppointments.Date > #WeekStartDate AND PatientsAppointments.Date < #WeekFinishDate) AND (PatientsAppointments.Status = 'Fulfilled') AND " & _
"(PatientsAppointments.DoctorID = #DoctorID) AND (AppointmentTypes.AppointmentName <> 'Note')"
'didn't get the error here... but just in case...
WeekFulfilled = mySQL.ExecuteScalar
Catch ex As Exception
ErrorSender.SendError("frmAppointmentBook - RefreshHeader 2", ex, New String() {String.Format("mySQL.commandtext: {0}", mySQL.CommandText)})
End Try
conSLDB.Close()
End Using
End SyncLock
The exact error message is:
System.InvalidCastException
Conversion from string "Needs Attention DC" to type 'Integer' is not valid.
Your problem has nothing to do with the COUNT(*) portion of your code. The problem is somewhere else in your query. What that particular error is telling you is that at some point you are comparing a character field (it probably usually contains numbers) to an integer field. One of the values of the character field happens to be "Needs Attention DC". If I had to guess it is probably either patientsappointments.appointmenttypeid or appointmenttypes.appointmenttypeid. Double check the datatype of each of those columns to make sure they are in fact INT. If they are both INT then start checking the other explicitly named columns in your query to see if you have any surprises.
You must have an error somewhere in your implementation...
Per the documentation, count always returns an int data type value.
Since this doesn't always happen, it must be a result of one of the paramenter values that is sent in. This is one of the lbuiggest problems with using dynamic SQL. What I would do is create the dymanic SQl and then store it in a database logging table with the date and time and user who executed it. Then when you get the exception, you can find the exact SQL code that was sent. Most likely you need more controls on the input variables to ensure the data placed in them is of the correct data type.
I am going to make another guess. I am guessing that this is a multi threading issue. You probably are sharing the connection between multiple threads. Once in a while the thread will get that man from somewhere else and execute it. Make sure that the connection variable is local, and only one thread can access it at a time.
As Martin points out, the following answer is wrong. I'm keeping this here to show that this is wrong.
From what everyone has already said, there is a type mismatch on your columns. Since your where clause appears to be fine, and your join is fine, it must be elsewhere. I would check to see if patientsappointments or appointmenttypes are views. Maybe the view has a join that's throwing the exception. Check the schema definition of all your joins/where's. Somewhere in there you're storing integers in a character field. It's fine for most rows, but one of them has your string.
If it's not in your views, it may be a trigger somewhere. The point is that somewhere there is a schema mismatch. Once you find your schema mismatch, you can find the row by querying for that string.

sql server: how do i get the last record that was inserted?

i am doing this:
With rs
.AddNew ' create a new record
' add values to each field in the record
.Fields("datapath") = dpath
.Fields("analysistime") = atime
.Fields("reporttime") = rtime
.Fields("lastcalib") = lcalib
.Fields("analystname") = aname
.Fields("reportname") = rname
.Fields("batchstate") = bstate
.Fields("instrument") = instrument
.Update ' stores the new record
End With
' get the last id
Set rs = cn.Execute("SELECT SCOPE_IDENTITY()", , adCmdText)
this is not working properly. it is returning NULL
It's not working because your updates and your second execute are in different scopes.
You may want SELECT IDENT_CURRENT('tablename')
IDENT_CURRENT is fine in a single user environment.
You're already on the record when you update.
.Update
lTheNewID = .Fields("ThisTableID")
lTheNewID will hold the value of the new record.

How to know whether a sql Update statement executed successfully or failed?

How to know whether a sql Update statement executed successfully or failed ?
I use sql server 2005 and C# asp.net.
Can I get the successful or failed infomation in C# without adding some sql code into the old sql statement?
You can use ##ROWCOUNT to get the number of rows affected by the last query. This can be used to decide whether your WHERE clause actually matched something, for example.
UPDATE mytable SET
field = 'SomeValue'
WHERE
id = 1234
IF ##ROWCOUNT = 0
BEGIN
-- No row with id=1234
END
You can use the return value of the ExecuteNonQuery to check if the update was successful or not.
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
SqlCommand cmd = new SqlCommand("sp_updateData", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p1 = new SqlParameter("#id", SqlDbType.Int);
p1.Value = 1;
p1.Direction = ParameterDirection.Input;
SqlParameter p2 = new SqlParameter("#name", SqlDbType.VarChar,50);
p2.Value = "sls";
p2.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p1);
cmd.Parameters.Add(p2);
try
{
con.Open();
//count will be the number of rows updated. will be zero if no rows updated.
int count = cmd.ExecuteNonQuery();
if (count > 0)
{
Console.WriteLine("Update Success!!!");
}
else
{
Console.WriteLine("No Updates!!!");
}
Console.ReadLine();
}
catch (SqlException ex)
{
Console.WriteLine("Update Failed coz.. " + ex.Message);
}
finally
{
con.Close();
}
What does 'failed' mean?
If by failed you mean an error was generated - SQL Syntax, constraint- or FK-violation - then TRY/CATCH, RAISEERROR, etc. are options.
Or, if by failed you mean no rows were updated, then the return value of ExecuteNonQuery will give you a rowcount IF you're not suppressing rowcount in your stored procedure.
Using a TRY/CATCH block and maybe RAISERROR to send a message.
http://msdn.microsoft.com/en-us/library/ms179296.aspx
http://msdn.microsoft.com/en-us/library/ms178592.aspx

Resources