[Microsoft][ODBC SQL Server Driver][SQL Server]Changed database context to 'dbname' - sql-server

I have a form with a textarea field that has about 250k of html in it. I'm posting it to an ASP page that is calling a stored procedure and inserting the text into a table. The field type and stored procedure parameter are both varchar(max). This page works fine when I post smaller html sets but give me the error.
[Microsoft][ODBC SQL Server Driver][SQL Server]Changed database context to 'dbname'
when I use large HTML data sets. Any ideas what the problem is?
ASP
Dim addRS, addCMD
Set addCMD = Server.CreateObject("ADODB.Command")
addCMD.ActiveConnection = objconn
ddCMD.CommandType = adCmdStoredProc
addCMD.CommandText = "insert_emailjob"
addCMD.Parameters.Append(addCMD.CreateParameter("emailbody",adlongVarchar,adParamInput,10000000,emailbody))
set addRS = server.createobject("ADODB.Recordset")
addRS.CursorLocation = adUseClient
addRS.open addCMD
PROC
ALTER PROCEDURE [dbo].[insert_emailjob]
#emailbody as varchar(max)
AS
BEGIN
INSERT INTO emails (emailbody) VALUES (#emailbody)
END

there is a default iis limit of uploading more than 100k in one form field
http://technet.microsoft.com/en-us/library/aa996475(v=exchg.80)

Related

Determining if a SQL Server table has IDENTITY column from MS Access VBA over ODBC

I have an MS Access program that constructs a SQL INSERT statement that inserts rows from an Access table into a linked SQL Server table with the same table structure. The SQL Server table may or may not have an IDENTITY primary key.
The MS Access source table has its corresponding primary key pre-populated, and these values must be inserted into the SQL Server table for referential reasons. SQL Server won't allow this unless I toggle the IDENTITY_INSERT property, but to decide if I need to toggle I need to determine if there is an IDENTITY column in the first place.
So in VBA from MS Access I need to determine if the linked SQL Server table has an IDENTITY column.
This question is covered here but for Transact-SQL.
I actually can get what I need using a pass-thru query, so it is feasible.
Create a pass-thru query to the SQL Server database.
In the SQL view enter
SELECT OBJECTPROPERTY(OBJECT_ID(N'table_name'), 'TableHasIdentity') AS 'HasIdentity'
and execute, it returns a 1-row datasheet with column HasIdentity that has value 1 if the table has an IDENTITY column.
The problem is that in VBA I cannot get at this datasheet. Given the query runs OK from MS Access I think the datasheet must correspond to a recordset and the following code should work.
Public Function metaODBCExecuteSQL(ByVal pstrConn As String) As Recordset
Dim qdf As QueryDef
Dim rst As Recordset
Set qdf = CurrentDb.CreateQueryDef("ODBC Execute")
qdf.ReturnsRecords = True
qdf.Connect = pstrConn
qdf.SQL = "SELECT OBJECTPROPERTY( OBJECT_ID(N'table_name'), 'TableHasIdentity') AS 'HasIdentity'"
Set rst = qdf.OpenRecordset(, dbSeeChanges)
qdf.Close
Set metaODBCExecuteSQL = rst
END Function
Instead the set rst line returns a run-time error 3219 invalid operation (with or without dbSeeChanges, which I believe is necessary for working with tables with IDENTITY).
Can anyone point out how I can retrieve the result set from the SELECT OBJECTPROPERTY query? What is wrong with my code, or is there another way.
After all if the MS Access UI can do it there must be a way.
If I create and save the query, this works great here:
? metaODBCExecuteSQL("")(0)
' Returns 0 or 1.
using this function and adjusting table_name to some valid table name:
Public Function metaODBCExecuteSQL(ByVal pstrConn As String) As Recordset
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Set qdf = CurrentDb.QueryDefs("ODBC Execute")
qdf.SQL = "SELECT OBJECTPROPERTY( OBJECT_ID(N'table_name'), 'TableHasIdentity') AS 'HasIdentity'"
Set rst = qdf.OpenRecordset()
qdf.Close
Set metaODBCExecuteSQL = rst
End Function

Not possible to update value of encrypted column

I have used Always Encrypted to encrypt values in a column. My connection string looks like this (everything is working fine and the client is able to decrypt the values):
Driver={ODBC Driver 13 for SQL Server};Server=10.10.10.1\INST2;Database=test;Trusted_Connection=yes;ColumnEncryption=Enabled;
Then I try to update one of the encrypted values using the following code:
ALTER PROCEDURE dbo.usp_SecurityUsers_GetDetails
(
#Firstname NVARCHAR(128)
)
AS
BEGIN;
UPDATE SecurityUsers
SET FirstName = #Firstname
WHERE login = 'system.export.service'
SELECT Login, FirstName, LastName
FROM SecurityUsers
END;
the SP is called like this:
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = conn
cmd.NamedParameters = True
cmd.CommandText = "[dbo].[usp_SecurityUsers_GetDetails]"
cmd.Parameters.Append cmd.CreateParameter("#Firstname", adLongVarWChar, adParamInput, 128, "system_text")
cmd.CommandType = adCmdStoredProc
Set recordSet = cmd.Execute
But I get the following error:
[Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Encryption
scheme mismatch for columns/variables '#P1'. The encryption scheme for
the columns/variables is (encryption_type = 'PLAINTEXT') and the
expression near line '1' expects it to be (encryption_type =
'RANDOMIZED', encryption_algorithm_name =
'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name =
'CEK_SecurityLevelNormal', column_encryption_key_database_name =
'test') (or weaker).
It's very strange, because I am able to update the field if the code is not encapsulated in stored procedure and directly executed in the SQL Server Management Studio.
Also, calling the SP directly in the SSMS works.
EDIT:
Updating to .net 4.6.3 does not change anything. What I am seeing is, if I change the connection string ColumnEncryption=Enabled; to Column Encryption Setting=Enabled;, I am getting different error:
[Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Operand type
clash: ntext is incompatible with nvarchar(128) encrypted with
(encryption_type = 'RANDOMIZED', encryption_algorithm_name =
'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name =
'CEK_SecurityLevelNormal', column_encryption_key_database_name =
'test')
I was feeling that the issue must be in the way I am trying to modify the data as I am able to read it. And it was so lame.
In my stored procedure I have nvarchar(256). In the ASP I am using adLongVarChar instead adVarWChar. The error seems more reasonable now:
Encryption scheme mismatch for columns/variables '#P1'.
The conclusion is one is able to read encrypted data and modify it using ADO and ODBC driver.

Executing Stored Procedure From MS Access Causes Timeout

The weirdest thing. I have a simple procedure that I developed in Microsoft Access 2010 with a SQL Server 2012 backend. I am now trying to deploy this into production which is Access 2016 and a SQL Server 2014 backend.
I've compiled, compact and repaired in the new environment... but I can not get Access to execute this simple stored procedure. Even worse it still executes several other stored procedures fine... but a couple of them it times out and refuses to execute?
Here is my VBA and stored procedure:
Private Sub GenerateUnitKey(UnitColumns As String)
Dim Msg, Style, Title, Response As Variant
Dim lngProcessID As Long
Dim Conn As ADODB.Connection
Dim Cmd As ADODB.Command
Dim CurrentConnection As String
CurrentConnection = LinkMasterConnection()
Msg = "Are you sure you want to update the UnitKey with the selected columns?"
Style = vbYesNo + vbCritical + vbDefaultButton2
Title = "Save Campaign?"
Response = MsgBox(Msg, Style, Title)
If Response = vbYes Then
Call OpenSixHatLoader("Generating Unit Key Across Campaign Records", 1, "")
Set Conn = New ADODB.Connection
Conn.Open CurrentConnection
Set Cmd = New ADODB.Command
With Cmd
.ActiveConnection = CurrentConnection
.CommandText = "usp_GenerateUnitKey"
.CommandType = adCmdStoredProc
.CommandTimeout = 30
.Parameters.Append .CreateParameter("#UnitColumns", adVarChar, adParamInput, 4000, UnitColumns)
.Execute
End With
End If
End Sub
And stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_GenerateUnitKey]
#UnitColumns AS VARCHAR(4000)
AS
SET NOCOUNT ON
DECLARE #SQL AS VARCHAR(MAX)
UPDATE tblStagingTable SET UnitKey =''
SET #SQL = 'UPDATE tblStagingTable SET UnitKey = ' + #UnitColumns + ' FROM tblStagingTable st'
EXEC(#SQL)
-- UPDATE Interests to match Staging Table
UPDATE tblInterests SET UnitKey = st.[UnitKey] FROM tblInterests i
INNER JOIN tblStagingTable st ON i.StagingTableID = st.StagingTableID
I am fairly confident there is nothing wrong with the code... as I said it worked fine in my development environment... even more I am manually able to execute the stored procedure within SQL Server. My SQL Server Native Client 11.0 connection works in executing other stored procedures... but for a couple of them it does not work. I am thinking I need to configure something within SQL Server itself or maybe within the Native Client 11.0 driver?
Unfortunately it gives no exception. I've set the CommandTimeout property to 0 and let it chug for a few hours hoping it would throw and exception to give me a clue but nothing... it just was frozen trying to execute. Any suggestions or ideas would be greatly appreciated because this one has me really stumped because it should be fine!
I would first launch SSMS, and from the SQL studio type in
Exec xxxxx ''
And ensure it runs (and use the SAME logon and connection to SSMS that you currently have for Access.
I would also consider creating a pass-though query, and saving that query in access. (set returns records = false if the sp does not return records). Then in code to run any proc, you can go:
With CurrentDb.QueryDefs("qryPass")
.SQL = "exec usp_GenerateUnitKey '" & UnitColumns & "'"
.Execute
End With
You note how simple the above code is - so if sp works from SSMS, then try the above code.
This was a difficult one that took me about 3 solid days of troubleshooting to get a solution to. Although I am not satisfied with the end solution as it should have just worked... but in the end my theory of the server being an Virtual Machine proved correct. When I deployed this exact same setup to Microsoft Access 2016 32 bit and SQL Server 2014 32 bit on a dedicated server it worked exactly as it was supposed to compared to the Azure VM and 1&1 Cloud Servers I had attempted to deploy to.
SQL Server integration with VM's is getting better from what all I have read, but apparently there is a ways to go. Maybe SQL Server needs to release a special VM version. Thank you to all those who took the time to look into this.

Copy records from one database to another (Teradata to SQL Server)

I have a project where I need to query a Teradata database and then copy the records returned to a SQL Server database. I can hit the Teradata db no problem and I can get the results into a DataTable. The SQL server db is already setup and has the same columns as the Teradata results (except for the auto id column). I am having trouble figuring out how to take the records in the DataTable and insert them into the SQL server db.
Here is what i have with some pseudo code where I didn't think the details were relevant:
Using cn As New TdConnection("User Id=XYZ12345;Password=XYZ12345;Data Source=teradataserver.company.com;Persist Security Info=False")
cn.Open()
Dim cmd As TdCommand = cn.CreateCommand()
'build the SELECT part of the command we will issue
cmd.CommandText = GetTeradataSqlString()
'setup the DataAdapter
Dim da As New TdDataAdapter(cmd)
' Provider specific types will be used in the data table
da.ReturnProviderSpecificTypes = False 'True=Use Teradata types, False=Use .NET types
' Adapter will determine how many statements will be batched
da.UpdateBatchSize = 0
Dim cb As New TdCommandBuilder(da)
'create a DataTable to hold our returned data
Dim dtCheck As New DataTable("TableCheck")
' Filling the data table with data retrieved from the select statement
da.Fill(dtCheck)
'create a DataSet to hold all of our tables
Dim dsMain As New DataSet("MainDataset")
'now we add the DataTable to our DataSet
dsMain.Tables.Add(dtCheck)
'at this point a cycle through the DataTable to the debug window shows we have the data we need from the Teradata db.
'now we will pump it into our SQL server database
Dim connSqlSvr As New System.Data.SqlClient.SqlConnection
connSqlSvr.ConnectionString = "Data Source=DestSqlServer;Initial Catalog=DestDb;Connect Timeout=15"
connSqlSvr.Open()
'now we create a SQL command to take the data in the Teradata DataTable and insert it into the SQL server table
Dim sqlCmd As New SqlCommand
With sqlCmd
.CommandType = CommandType.Text
Dim sbSqlCmd As New StringBuilder
sbSqlCmd.AppendLine("INSERT INTO [DestDb].[dbo].[Events] ([CityCode],[CarNum],[VIN],[Fleet],[EventItm])")
sbSqlCmd.AppendLine("SELECT City,CarNo,VIN,Fleet,EventDesc FROM #MyTable;")
.CommandText = sbSqlCmd.ToString
Dim sqlParam As New SqlParameter
sqlParam.ParameterName = "#MyTable"
sqlParam.SqlDbType = SqlDbType.Structured
sqlParam.Value = dtCheck
sqlParam.TypeName = "TableCheck"
.Parameters.Add(sqlParam)
.Connection = connSqlSvr
Dim rowsAffectedLoad As Integer = .ExecuteNonQuery()
debug.print(rowsAffectedLoad & " rows were loaded into the SQL server table.")
End With
'close and dispose the SQL server database connection
connSqlSvr.Close()
connSqlSvr.Dispose()
End Using
Running the code I get an exception:
"Column, parameter, or variable #MyTable. : Cannot find data type TableCheck."
I've looked for a method to insert a DataTable into a database and noticed many samples were using the INSERT INTO. I just dont think I am using the SqlParameter properly.
Your example appears to be using a Table Valued Parameter of type TableCheck but you have not defined that type within SQL Server. See http://msdn.microsoft.com/en-us/library/bb510489.aspx
CREATE TYPE LocationTableType AS TABLE
( LocationName VARCHAR(50)
, CostRate INT );
Although I can't guarantee that you can pass a TVP directly into a raw SQL statement.
I would actually suggest you use a different approach using SqlBulkCopy, http://msdn.microsoft.com/en-us/library/ex21zs8x(v=vs.110).aspx .

Passing Large XML data to xml datatype parameter in ADODB

I have a procedure that takes a xml datatype parameter
create procedure my_procedure
#xml_parameter xml
as
begin
(...)
end
And i call that procedure from a classic asp page, using a command like this:
set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = MyConnObj
cmd.CommandText = "my_procedure"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter("#xml_parameter", adLongVarChar, adParamInput, Len(xmlData), xmlData)
It's working if i pass a small xml. But when i pass a large xml, +- 200 Kb, I get the message "The procedure expects the #xml_parameter parameter, wich was not informed".
Does anyone know how i can pass this xml to the stored procedure?
PS: It also works when i call the procedure from "SQL Server Management Studio" with the same xml data, so it seems the limitation is from the ADO.
Edit in 2014-jun-19:
Debugging the problem i discovered a message from ODBC Driver saying that some data are being truncated. I tried to change the driver, by using "Driver={SQL Server Native Client 11.0}", but now i get the message : "The metadata could not be determined because statement (...) uses a temp table"
I was able to successfully submit over 7MB of data into procedure's parameter by using ADODB 2.8, Parameters.Refresh method to initially build the parameters, AppendChunk method to built its value and changing parameter's type to adLongVarWChar before execution (originally it was adVarWChar)
.Refresh query the database for parameters, hence you get an extra DB communication.
all need to be done instead of refresh is pass the length as Len+1, for the null terminating character.

Resources