Hi I have a query that can not be represented graphically in Excel External SQL Server Query, because the query is not simple I can not set Excel Variables. Instead I try to set variables in the SQL using declare/set however when doing this it fails when trying to import the data.
Is there a way to get around this? I need a level of flexibility for running the query and piping the data into Excel..
Okay so here is an example as requested.
declare #enddate as datetime
set #enddate = (select max(rpt_week) from [results].dbo.t_Data)
Select * from results.dbo.t_Data
where rpt_week = #enddate
This will not run in excel, obviously my query is more complex but the use of variables is essential and I am looking for a way to have this work.
Thanks
When using declare values in Excel, you need to SET NOCOUNT ON
your sample would be as follows:
SET NOCOUNT ON;
declare #enddate as datetime
set #enddate = (select max(rpt_week) from [results].dbo.t_Data)
Select * from results.dbo.t_Data
where rpt_week = #enddate
There is another question on this subject which has a correct answer:
Use SET NOCCOUNT ON in your query.
I encountered the same problem as the OP when I tried to run an SP from Excel, which was supposed to return data from an embedded SELECT. It was caused by a ... row(s) affected message being returned from the server. Apparently, Excel can't deal with this message correctly, and the returned data is ignored. Once I used SET NOCOUNT ON in my SP, the data was displayed correctly in Excel.
I am not quite sure what you wish, but here are some notes:
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim cmd As New ADODB.Command
cn.Open ServerCon ''Connection string
''Straight sql
sSQL = "SELECT * FROM table_1 WHERE adate = (SELECT Max(adate) FROM table_1)"
rs.Open sSQL, cn
''Not a good idea, see procedure parameter below for a better way
sSQL = "SELECT * FROM table_1 WHERE adate = '" _
& Sheets("Sheet7").Range("B2") & "'"
rs.Open sSQL, cn
''Stored procedure
rs.Open "ExcelTest", cn
''Stored procedure with parameter
cmd.ActiveConnection = cn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "ExcelTest"
cmd.Parameters("#enddate") = Sheets("Sheet7").Range("B2")
Set rs = cmd.Execute
''Write to Excel
ActiveWorkbook.Sheets("Sheet12").Cells(1, 1).CopyFromRecordset rs
You can also use Query Tables.
Related
I'm pulling into Excel VBA from a SQL ADODB Connection and it seems that some fields are coming back as empty that have values in SQL. I'm very green in VBA (just diving back into a legacy application to try and migrate everything to SQL Database storage instead of CSVs)
Here's an example of the value return (just a " where we should have "Sample Data | QRSTE/ S179399")
The code to pull:
Sub GetDFInfoByDf(recordID As String, connectionString as String)
Dim connectionString As String
connectionString = connectionString
Dim command As String
command = "Select * FROM data_table WHERE id = '" & recordID & "'"
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
conn.Open connectionString
rs.CursorLocation = adUseClient
rs.CursorType = adOpenStatic
rs.LockType = adLockBatchOptimistic
Set rs = conn.Execute(command)
Dim rsMatrix As Variant
rsMatrix = rs.GetRows(1)
If IsNull(rs) Then
'rs is null
MsgBox "Pulled recordset is null"
Else
Call FillObjValuesFromRecordSet(rs)
End If
I see that we have a somewhat special character in there (|)
In terms of any SQL Encoding configurations: It's most likely UTF-8. I would think that I have to convert that to ANSI either in VBA or on the SQL side, but have been running in circles to try and figure that out.
Note that this field is NVARCHAR in SQL
Any ideas on how to handle this? Documentation is very sparse on the subject, from what I've seen.
Thanks!
Things I've Tried:
Adding Session Mode=ANSI; to the connection string
Expected Outcome:
-SQL stores the varchar "Sample Data | QRSTE/ S179399" (no quotes in the field)
-I'm expecting my Select to return that exact varchar/string value instead of the return in the image (")
Solution:
My SQL table columns with varchar(max) or nvarchar(max) were not able to translate back.
My initial table had larger-than-needed sizes, so altering those columns to varchar(8000) and nvarchar(4000) fixed the issue!
Thanks
I am trying to breakdown my SQL string in Excel VBA, storing my variables in the first part of the SQL, and calling them in the second part. It seems that declared variables is not my friend here?
First part(Declaring my variable)
Dim rst As ADODB.Recordset
Dim cnn As ADODB.Connection
Dim sSQL As String
Set rst = New ADODB.Recordset
rst.CursorLocation = adUseClient
rst.LockType = adLockReadOnly
Set cnn = New ADODB.Connection
cnn.CommandTimeout = GCL_dbTimeout
cnn.Open "XXX"
rst.ActiveConnection = cnn
sSQL = "DECLARE #Id AS INT = 1234 ; SELECT #Id AS [Id] INTO #cte_TEMP;"
cnn.Execute (sSQL)
Second part(Calling my variable)
Using a temp table works:
rst.Open "SELECT * FROM #cte_TEMP;"
But calling the variable doesn't:
rst.Open "SELECT #Id;"
In-memory #variables are only in-scope during the execution of a single command; once rst.Open returns, the variable is gone and no longer exists.
By storing it into a #temp table, you are persisting the value to physical disk storage, which leaves it available to other subsequent commands.
Don't forget to DROP TABLE #cte_TEMP; at one point! :)
Note: #temp tables are only accessible from the user that created it. If you need to access it from a different connection string, you need to use ##temp tables instead.
I'm using Excel/vba to send query to SQL Server. The query is something like:
using database
declare #queryString as nvarchar(max)
create table #tempTable (col1 int, col2 int, col3 int)
insert into #tempTable
select top 10 col1, col2, col3
from sometable
set #queryString='select * from #tempTable where col1>10'
exec(#queryString);
If I run this query in SQL Server Management Studio, I get the desired results, but when I run it from Excel/vba, I get an error
Operation is not allowed when the object is closed.
I tried to pass it to SQL Server Management Studio like this (where queryExample is my query):
Dim rs As New ADODB.Recordset
Set Connection = New ADODB.Connection
Connection.ConnectionString = "... connection string ..."
Connection.Open
With rs
.ActiveConnection=Connection
.Open queryExample
End With
and like this
Dim rs As New ADODB.Recordset
Dim cmd As New ADODB.Command
Set Connection = New ADODB.Connection
cmd.CommandText = queryExample
cmd.CommandType = adCmdText
cmd.ActiveConnection = Connection
Set rsSR = cmd.Execute
but nothing is working, and I always get the same error. I think that problem is in exec() function, because if I pass query like this:
select top 10 col1, col2, col3 from sometable
I don't get any error and recordset is populated with data.
What am I doing wrong? Any help would be appreciated.
Thanks.
EDIT:
I made a mistake when copying vba code for the last example to pass the query to SQL Server Management Studio, the actual code was:
Dim rs As New ADODB.Recordset
Dim cmd As New ADODB.Command
Set Connection = New ADODB.Connection
Connection.ConnectionString = "... connection string ..."
Connection.Open
cmd.CommandText = queryExample
cmd.CommandType = adCmdText
cmd.ActiveConnection = Connection
Set rsSR = cmd.Execute
Conection was opened in both cases - value of .State of Connection object was 1.
I'm trying to read from different Tables on a Oracle Database using VBA and Excel.
Usually when read the tables I run something like:
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
Dim query As String: query = "SELECT * FROM OBJ_NAME"
rs.Open query, con
However, this does not work for all the tables. Using SQL Developer i usually run at the beginning:
exec session#.open_session();
After which I can read any table. Is there a way to run this command with an ADODB.Recordset in the beginning too? Just replacing the SQL Query with the command did not work.
Or is there different way to read this 'hidden' Tables?
Try something like that:
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
Dim query As String: query = "begin session#.open_session; end;"
With rs
.ActiveConnection = con
.Open query, con
End With
Set connectToDB = con
This should work using VBA. Let me if it worked :)
I have lots of SQL scripts, many of which use various different variables throughout, and I'd like to be able to drop the results directly into Excel. The hope is to do this as 'smoothly' as possible, so that when someone gives me a new SQL script (which may be relatively complicated), it is relatively clean to set up the spreadsheet that gathers its results.
Currently trying to get this working using ADODB Command objects parameters, but I can't even manage to get a very basic example to work. I have the following VBA:
Dim oConnection As ADODB.Connection
Set oConnection = New ADODB.Connection
oConnection.ConnectionString = "MyConnectionString"
oConnection.Open
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
cmd.ActiveConnection = oConnection
Up to here is just setting up the connection, which seems to work fine.
cmd.CommandText = "DECLARE #DateID integer;" & _
"SELECT TOP 10 * FROM dbo.SomeRecords " & _
"WHERE DateID = #DateID"
cmd.CommandType = adCmdText
Dim DateID As ADODB.Parameter
Set DateID = cmd.CreateParameter("#DateID", adInteger, adParamInput)
cmd.Parameters.Append DateID
DateID.Value = 20120831
Dim rst AS ADODB.RecordSet
Set rst = cmd.Execute()
ActiveSheet.Range("A1").CopyFromRecordset rst
Unfortunately, this doesn't return anything. However, if I replace the line:
"WHERE DateID = #DateID"
with this:
"WHERE DateID = 20120831"
Then the query returns exactly what you'd expect (the top 10 records from August 31), so obviously I'm not passing the value of the variable from VBA into SQL properly, but I have to admit that I'm pretty much stuck.
Certainly something is being passed into SQL (if I change the type of the variable #DateID to datetime in the SQL, then I get a SQL Server arithmetic overflow error, from trying to convert something to datetime), but it isn't doing what I was expecting.
I guess there are two questions: Is there a way to fix this code? Is there a better way of achieving the general goal described at the start?
Try this
cmd.CommandText = "DECLARE #DateID integer;" & _
"SET #DateID = ?DateID;" & _
"SELECT TOP 10 * FROM dbo.SomeRecords " & _
"WHERE DateID = #DateID"
.....
Set DateID = cmd.CreateParameter("?DateID", adInteger, adParamInput)
Re:
in which case why bother having names for them in the first place
Well, so that you can match them up as shown above. By all means use it many times, but use a sql-server local declare and set it there as shown.
Remove the DECLARE #DateID integer; from the SQL string.
ie:
cmd.CommandText = "SELECT TOP 10 * FROM dbo.SomeRecords " & _
"WHERE DateID = #DateID"
Parameters in an ADO parameterized query want a ? as placeholder so:
"SELECT TOP 10 * FROM dbo.SomeRecords WHERE DateID = ?"