I am attempting to use XML that was generated from a stored procesure in our MS SQL database as a Recordset in a VS2005 Application. The issue I am having is that when reading in the xml as a string, the string result comes in as "System.Byte[]". Seeing this I changed the datatype from String to Byte() and tried to use the Byte array. The Byte array does not seem to have anything to do with the data I want to be receiving. I am wondering if there is a way to handle SQL generated XML files that I am not aware of. Here is some sample code.
This is what the result of the stored procedure looks like when in SQL SMS
With this code I get the System.byte[] as my string:
Dim ADOrs As ADODB.Recordset
Dim SQLString1 As New System.Text.StringBuilder(180)
Dim catzzz as String
SQLString1.Append("exec reports_selectReportMetaData #companyCode = '001'")
ADOrs = fnReturnRecordset(SQLString1.ToString) 'function executes the query
Do While Not ADOrs.EOF
catzzz = ADOrs("XML_F52E2B61-18A1-11d1-B105-00805F49916B").Value.ToString
Debug.WriteLine(catzzz)
Loop
This is the way I get the really odd Byte Array
Dim ADOrs As ADODB.Recordset
Dim SQLString1 As New System.Text.StringBuilder(180)
Dim catzzz As Byte()
SQLString1.Append("exec reports_selectReportMetaData #companyCode = '001'")
ADOrs = fnReturnRecordset(SQLString1.ToString)'function executes the query
Do While Not ADOrs.EOF
catzzz = ADOrs("XML_F52E2B61-18A1-11d1-B105-00805F49916B").Value
Loop
The Byte array looks like
And when converted to ASCII using
catX = System.Text.Encoding.Default.GetString(catzzz)
the first three characters (that should be <rt ) Come up as
So I think my main issue is that I am missing the proper way to bring in the XML created in SQL
Any Ideas would be appricated!
Ended up changing from a stored procedure to a function so that we would be returend a value instead of just having the command executed. This solved the System.Byte[] issue.
Related
I try to save data from TextBox1.Text value to a SQL Server database in column of type Decimal(18, 0). I use VB.NET and SQL Server database.
I format the data in the textbox value to number for example "200,000".
When I try to save, I get this error
Error converting nvarchar to numeric
I can't use Val(Textbox1.text) because he take only "200" not "200000"
How can I fix this?
18 precision 0 scale is essentially a Long, so you should use Long.Parse() or Long.TryParse() to get the real numeric value in VB. This will give you more control than the antiquated Val() over things like separator characters.
Then, in the SQL part, make sure you're using a parameterized query with the appropriate type for the parameter:
Dim data As Long = Long.Parse(Textbox1.Text)
Dim sql As String = "INSERT INTO [someTable] (column) VALUES (#parameter)"
Using con As New SqlConnection("connection string here")
Using cmd As New SqlCommand(sql, con)
cmd.Parameters.Add("#parameter", SqlDbType.Decimal, 18, 0).Value = data
con.Open()
cmd.ExecuteNonQuery()
End Using
I am querying SQL Server from VBA using ADODB. All of my tables have RowVersion (timestamp/varbinary) columns. Since VBA doesn't support the varbinary type, I convert the RowVersion to a string from a SQL Server function. A simple query will look like:
sql = "SELECT NameValueListID, dbo.RowVersionToString(RowVersion) AS RowVersion FROM NameValueLists WHERE NameValueListID=1
To get the data onto a sheet, I first tried range.CopyFromRecordset. This worked until I included the above function in the sql call. Adding the RowVersionToString function caused the recordset to return what seems like a random set of data - less rows than excepted and fewer column than I asked for. Never could figure that one out. I then used rs.GetRows which returned the expected data and I could use range.value = rsData successfully. Below is a sample call that works.
Private Sub Test_Scratch()
Dim rs As ADODB.Recordset
Dim sqlCmd As New ADODB.Command
Dim sqlConnection As ADODB.Connection
Dim sql As String
Dim rsData() As Variant
Set sqlConnection = New ADODB.Connection
sqlConnection.Open ModSQL.GetConnectionStringByStage(wsSetup.Range("suAppStage"))
sql = "SELECT NameValueListID, dbo.RowVersionToString(RowVersion) AS RowVersion FROM NameValueLists WHERE NameValueListID=1"
Set sqlCmd.ActiveConnection = sqlConnection
sqlCmd.CommandText = sql
Set rs = sqlCmd.Execute
rs.MoveFirst
rsData = rs.GetRows
End Sub
I then added a second varbinary column to the query (it's not a RowVersion but is of the same type). So the sql will look like:
sql = "SELECT NameValueListID, dbo.RowVersionToString(RowVersion) AS RowVersion, dbo.RowVersionToString(LastItemRowVersion) AS LastItemRowVersion FROM NameValueLists WHERE NameValueListID=1
After the call, the recordset rs has all the data, but rsData has "Empty" for the first varbinary column. The order doesn't matter. Only the last varbinary column has a value, the other is always "Empty" in the rsData array.
I guess,more could anser your question if you showed your code of user function RowVersionToString.What is the definition of argument of RowVersionToString?It might be that the argument "RowVersion" was interpreted to a data type not but a colmun name.
sql = "SELECT NameValueListID, dbo.RowVersionToString(NameValueLists.RowVersion) AS RowVersion, dbo.RowVersionToString(LastItemRowVersion) AS LastItemRowVersion FROM NameValueLists WHERE NameValueListID=1
I've been struggling all afternoon with trying to save a zip file in a varbinary(MAX) column in SQL Server. I think I've got the zip file saved as a binary array, but I just can't seem to get it saved to the database.
My connection:
Dim objConnection As OleDbConnection
Dim objCommand As OleDbCommand
objConnection = New OleDbConnection(strConn)
objConnection.Open()
Saving the zip file from disk to a binary array:
Dim filePath As String = Session("ZipFileName")
Dim filename As String = Path.GetFileName(filePath)
Dim fs As FileStream = New FileStream(filePath, FileMode.Open, FileAccess.Read)
Dim br As BinaryReader = New BinaryReader(fs)
Dim bytes As Byte() = br.ReadBytes(Convert.ToInt32(fs.Length))
br.Close()
fs.Close()
And then (trying to) save the file to my database:
strSQL = "UPDATE MyTable SET BinFile = #Data WHERE RecordID = '" & Session("RecName") & "'"
objCommand = New OleDbCommand(strSQL, objConnection)
objCommand.Parameters.AddWithValue("#Data", SqlDbType.Binary).Value = bytes
objCommand.ExecuteNonQuery()
I've been trying different variations of this idea for hours, including a handful from this site, but I keep getting the error
Must declare the scalar variable '#Data'
Can anyone help? Thanks.
As Plutonix suggests, your use of AddWithValue is incorrect. The whole point of AddWithValue is that you provide the name and value and the rest is inferred. The way you're calling it is what you would do with Add rather than AddWithValue, i.e. specify the type of the parameter yourself and then set the Value property afterwards. AddWithValue exists specifically so that you don;t have to do that.
Also, given that you are already doing the right thing and using a parameter for the BinFile column, why then break the rules and use string concatenation for the RecordID? Just do the right thing again and use parameters for both.
I got an SQL 2005 table with many (84 to be specific) fields (actually it is a query returned by a procedure)
It looks like when I access recordset fields placed later then some field placed earlier becomes empty while server had actually returned a value for it
Had anyone such problem?
My solution is to put such disappeared field at the end of a table so when it is accessed later by a code (here VBA) its value is still accessible BUT I see it as a big problem in ADODB.Recordset 2.8 as I should not care about field order
I know that question is not very specific but maybe someone had a similar issue?
One way to to make sure the field values are there is to pass on the recordset to a array like (You will have to build your own connection function):
Function getStoredProcedure() As Variant
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Dim conn As ADODB.Connection
Dim values As Variant
Set conn = getConn("Server", "Database")
Set cmd = New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "StoredProcedureName"
cmd.Parameters.Item("#TODAY") = today
Set rs = cmd.Execute
If Not rs.EOF Then
values = rs.GetRows
Else
Exit Function
End If
Set cmd = Nothing
getStoredProcedure= transposeArray(values)
End Function
From there you can always retrieve the values from the array. Otherwise, without seeing your code or understand what you are trying to do, I cannot tell if this is really an issue with ADODB because I cannot recreate this issue when pulling field items in any order I want such as: rs.Fields.Item(i).Value for i = any number in any order.
I met this problem twice. There are two exception fields in my query string. Running the query string in sql server, they can return the values but these two exception fields are empty when run the query string in VBA used recordset. I put these exception fields behind other normal fields in the query string, and then they can return value in the recordset instead of blank. So it's really a big problem.
i have to write a script that converts a string from a MSSQL Server database in sql_latin1_general_cp1_ci_as into a value in an XML file, which is in UTF8 encoding.
Does anyone have an idea how to do in in VBS?
Thanks!
you might need to add a bit more context to your question, but a first answer would be to query the database using ADODB, load your XML into MSXML2, use XPath to select the node in which you want to add your result then insert the string as the node text.
''#open the data
dim ado: set ado = CreateObject("ADODB.Connection")
ado.ConnectionString = "..."
ado.open
dim rs: set rs = ado.Execute("SELECT TOP 1 your_string FROM your_data_table")
''#open the XML
dim xmldoc: set xmldoc = CreateObject("MSXML2.DomDocument")
xmldoc.async = false
xmldoc.setProperty "SelectionLanguage", "XPath"
''# you might also need setProperty "SelectionNamespaces", "xmlns=..." depending on your XML
xmldoc.load "path\to\your\XML"
''# store the string in the XML and save
xmldoc.selectSingleNode("//xpath/to/your/target/node").text = rs.fields["your_string"].value
xmldoc.save "path\to\your\output\xml"
rs.close
ado.close
If you're already at this point, let me know if you are having any specific problems