I have made a macro that does the following:
Identifies SQL code written in Excel (Using named ranges)
Creates/saves a text file containing the SQL query
Runs the SQL query via an ADODB connection to SQL Server Management Studio 18
Returns the resulting recordset back into Excel (I have the 32-bit version)
I have tested the code for many queries, and it worked as expected. However, with one query, I receive "System Error & H80004005 (-2147467259)" when I attempt to open the recordset (The line "rs.open"). The only notable qualities of this query (stored in "rs.source") are:
The query is unusually long (Roughly 1,500 lines, whereas others were about 500)
It produces many records (Four output tables. Two are small, two with roughly 35,000 records each)
It accesses many data tables within SQL (9 tables)
After running a couple diagnostics, I feel pretty confident that:
My connection string is correct:
I have successfully used the same connection string for other SQL queries on the same server
The SQL query is correct, and is being stored correctly: I have manually copy, pasted and ran the text file (generated by the VBA code) in SQL Server Management Studio with success.
The recordset's source (in VBA) is able to hold the entire query: After assigning the recordset's source to the text file, I then wrote the recordset's source to a new text file to ensure it was storing the entire query. It was.
It isn't the number of records or tables being produced: I edited the query such that there is only one small recordset being produced, and I still get the same error.
I have tried to find other posts that encountered a similar error, but there didn't seem to be much out there for this issue (and the proposed solutions I found related to managing Add-ins). I will attach a snippet of the code, which errors on the line rs.Open. I'm relatively new to VBA, and extremely new to SQL (I did not write any of these SQL queries), so I apologize if I'm missing something obvious. Thank you for any guidance. Code Snippet
Related
Good morning,
I just received a new assignment and I am struggling with finding an appropriate solution. I have searched through the SO Forums, and through Google, but have not found a workable solution. Below is my scenario:
We are working out of Microsoft Access to connect to an SQL Server Database via an ODBC Connection.
I wasgiven an incredibly large pass-through SQL query, larger than is able to be processed in MS Access. In this pass-through query, there is a subquery in a WITH...AS method.
I am hoping to be able to split this one, singularly large, SQL pass through query into two: Query One (the subquery), and Query Two (which references the results of the subquery)
I know that by using general Access queries, I can write a Macro like follows...
Sub myQuery()
' Edited from http://www.dbforums.com/showthread.php?1667831-Run-multiple-queries-in-sequence-on-click
' On Error GoTo ErrHandler
' Run the first query
MsgBox "Starting first query"
DoCmd.OpenQuery "first_Query"
DoEvents
' Run the second query
MsgBox "Done. Now starting second query"
DoCmd.OpenQuery "second_Query"
DoEvents
MsgBox "Done!"
End Sub
However, these need to be pass-through queries. I believe that the enormously large SQL String is created via a number of user inputs. Regardless, I don't have the ability to change the pass-through SQL that I was given.
Is there anyway I can write a macro that calls the first pass-through query, and then calls the second pass-through query that REFERENCES the result of the first?
Here is an example with what I am working with...
WITH queryOne AS
(
SELECT fooID
FROM tblFoo
WHERE foodate > ...
)
SELECT foo, fooone, footwo, foothree
FROM tblOtherFoo
WHERE fooID = OtherFooID
However, the query is 50000+ characters, exceeding that ~37k limit.
Please feel free to ask any questions. I am stumped by this and would appreciate any feedback or alternative resources.
Thank you!
It not clear what you mean by something that references the first or previous? Why break up something you been given that supposed works just fine?
So just place that existing t-sql you been given into a stored procedure. In T-SQL you can easy have some SQL operate on some previous SQL, but why break up such a HUGE massive monster slew of code and introduce bugs? It will take you YEARS AND YEARS to break up a KNOWN working huge T-SQL that been built and developed for you (something that long likely took a few years and a team of developers to create).
A conservative estimate would be such a routine cost $50,000, or even $100,000 to develop.
No question that the working T-SQL you been given might reference previous data, or even do selects into #Temp tables that additional T-SQL can work on.
If you ALREADY have a working PT code and query given to you?
Simply take that T-SQL query, and simply paste it into a stored procedure. You will do this in SQL Server and NOT even touch or bother with Access.
So don't create some macro in Access that calls multiple separate queries, but place all of the T-SQL in a stored procedure, and simply call that huge mess one time from Access.
It possible that the T-SQL you been given is incorrect, but assuming that the T-SQL is correct, then simply place all that long mess into a working stored procedure. You do not place this SQL in MS Access and you don’t need to have that mess inside of Access.
So get that T-SQL working in SQL Server – don’t bother with MS Access until this long query mess is working in SQL Server. ONLY THEN do you fire up Access.
So you THEN create a simple PT query in Access that calls the huge long T-SQL mess you been given. But that “mess” is to be placed in SQL Server – not in Access.
So create a PT query in Access that calls your “supposed” working T-SQL you been given. The SQL you save in the Access PT query will be this
Exec my_StupidLongSQLProc
Save the above as a PT query. Then in VBA code go:
Currentdb.QueryDefs("MyPTQuery").Execute
If you need to pass some values from Access, then go:
With CurrentDb.QueryDefs("MyPTQuery")
.sql = "exec My_StupidLongSQLproc " & p1 & "," p2
.Execute
End with
In above we pass two VBA values from Access to the big mess of sql you have – the stored procedure in above is just an example that access two parameters passed from Access VBA. If the T-SQL you been given does not require values from Access, then the first single .execute will do the job.
And if you REALLY did get such a long routine that is correct T-SQL, then it likely already has parameters in the working T-SQL (and again you don’t want to mess with or change such a huge long working T-SQL that you been given).
So you only need one line of code in Access, and your existing long T-SQL you been given if written correctly can be placed in a stored procedure (assuming that you actually been given a correctly working PT query).
So if you REALLY did get a huge massive working T-SQL statement, then simply place that KNOWN AND WORKING T-SQL in SQL Server as a stored procedure and call it with one line of code as per above.
So trying to split this up from Access will only server to cause world-wide poverty and ANY tiny miss step or breaking up of that huge long routine will cause world-wide poverty and starving children as you try and “fix” this great working T-SQL that you been given. As noted, something that long to create would take a teams of developers HUGE resources. If you touch or break up one line of code and mess it up, then you need that team of developers to spend several months trying to fix what you broke.
So the INSTANT you start breaking up such a huge long mess is the instant you lost this battle and will waste several years of your life trying to fix this crazy long T-SQL that you been given that is already claimed to be proper working code.
I try to create a pretty complex database on ms Access 2013, so I wanted to type it directly in SQL. It has no errors, as other DBMS can fully build the database from the script I wrote (for example, phpmyadmin imports it with no difficulty).
On this tutorial, it is showed how to write a SQL query in order to build tables. I thought this way matched well with my goal as I could copy-paste my script in the query and run it to create the whole thing.
But when I tried to open/double-click on the query a pop-up appears saying "Select data source", waiting for me to select an ODBC, either from a file or a host, before continuing and executing the query.
I tried other types of queries (creating only one table at time, trying on a blank file, or even SELECT * FROM *), bt this message keeps showing up and I really don't know how to deal with it as I don't want to connect to anything but the infile database.
Does anyone got a hint about what to do in this case?
Or, even better, how could Access import my SQL script in order to create the database?
You should configure the database connection in the ODBC and check whether the connection is established or not. Once the connection is established, you can run the query to fetch the data or create tables as per your requirement.
I have an excel file that will select roughly 1100 rows with 5 columns of data. Most columns are 5 digits long and are integers. I am using a macro to connect to a SQL server database and insert these rows into one maybe two tables. This is all its doing and then it closes the connection. So the user opens an excel file that has the rows, clicks a button and it executes the macro.
My question is, should the query be written in Excel since its simple and merely inserts the data into a few tables. Or is it more efficient calling a stored procedure and passing all of the values in the stored procedure and have it allocate where the values go in the different tables. When I mean efficient, i mean which is the quickest? I know this will probably take a few seconds to complete. I just feel going to a stored procedure is an extra point along the path that the data has to get to before it reaches the tables. Am I wrong? Any thoughts?
There are some advantages to using stored procedures in SQL Server. One is that SQL Server precompiles and saves the query execution plan, which increases performance. With your current method, SQL Server will generally need to generate the execution plan each time. Stored procedures can also reduce client/server network traffic.
So, even though it may seem like an extra point along the path, it actually can be faster.
In addition to #mark d.'s answer, another reason for using a stored procedure is security.
Your comment says that a customer is entering the data into Excel, so if you are putting direct SQL into your spreadsheet, then there is a risk that someone will open your spreadsheet and find out information about your database. But if you use a stored procedure then there is far less that can be learned.
Either way, make sure that you aren't hardcoding any connection string/account credentials into the spreadsheet.
I have had an odd error I cannot explain. Basically, I am running a query to my SQL database using excel and am having non-existent data pop up when it comes to a very particular order in my database.
Here is a simple query surrounding this order:
select * from OR200100 where OR200100.OR20001='0000793605'
Here is the output in EXCEL
And here is the same output in SQL
what is happening here? How could the same query generate 2 different results?
Run SQL Server Profiler against the database if you can, then compare the output to the sql query that you are running in ssms.
OK, so it's SQL Server then, that's important because different SQL products can have very different idiosyncrasies and controls.
The next things to check are these:
Is OR200100 a Table or a View? If it's a view then post it's code.
Are you using the same Login/account from both Excel and SSMS?
Are you sure that you are connecting to the same Server and Database? SSMS tells you what you are connected to, but client apps like Excel do not and it is very common for this type of problem to be caused by the app connecting to a Dev or QA version of the database. See here for some of the different ways that this can happen:
So I had a very similar problem, my query was grouping by week numbers. What I found was that one of the queries had set datefirst 5 set whilst the other didn't. I guess the key thing here is make sure, if you are using any SET operations in your ssms queries, these are identical to those in the Excel query string.
Is it possible to search and replace all occurrences of a string in all columns in all tables of a database? I use Microsoft SQL Server.
Not easily, though I can thing of two ways to do it:
Write a series of stored procedures that identify all varchar and text columns of all tables, and generate individual update statements for each column of each table of the form "UPDATE foo SET BAR = REPLACE(BAR,'foobar','quux')". This will probably involve a lot of queries against the system tables, with a lot of experimentation -- Microsoft doesn't go out of its way to document this stuff.
Export the entire database to a single text file, do a search/replace on that, and then re-import the entire database. Given that you're using MS SQL Server, this is actually the easier approach. Microsoft created the Microsoft SQL Server Database Publishing Wizard for other reasons, but it makes a fine tool for exporting all of the tables of a SQL Server database as a text file containing pure SQL DDL and DML. Run the tool to export all of the tables for a database, edit the resulting file as you need, and then feed the file back to sqlcmd to recreate the database.
Given a choice, I'd use the second method, as long as the DPW works with your version of SQL Server. The last time I used the tool, it met my needs (MS SQL Server 2000 / 2005) but it had some quirks when working with database Roles.
In MySQL, you can do it very easily like this:
update [table_name] set [field_name] = replace([field_name],'[string_to_find]','[string_to_replace]');
I have personally tested this successfully on a production server.
Example:
update users set vct_filesneeded = replace(vct_filesneeded,'.avi','.ai');
Ref: http://www.mediacollege.com/computer/database/mysql/find-replace.html
A good starting point for writing such a query is the "Search all columns in all the tables in a database for a specific value" stored procedure. The full code is at the link (not trivial, but copy/paste it and use it, it just works).
From there on it's relatively trivial to amend the code to do a replace of the found values.