Single SQL query run against multiple linked SQL servers/DBs - sql

I have a single SQL query that I need to run against ~25 different databases- each residing on a separate SQL server on the network. The query will run from a single central SQL server management studio, and the 24 other SQL server instances are linked. I have the query I need, and I tested that it works- however the goal is to create a script that queries each of the 25 separate SQL instances.
Instead of writing the query out 25 separate times within the script, I'm wondering if there's a way to utilize the single block of code to query each of the linked instances using an array, variables, DO/WHILE, a function or any other method.
Here's the query:
SET NOCOUNT ON
PRINT 'local server';
SELECT isc.ini_schema_name[Device], count(*) [Count]
FROM pharos.dbo.edi_pharos_stations eps, pharos.dbo.ini_schemas isc
WHERE eps.ini_schema_id = isc.ini_schema_id
GROUP BY isc.ini_schema_id, isc.ini_schema_name
For the purpose of this example, if I were to utilize the less-graceful approach of writing out the block of code 24 more times, this would be the next query in the script (to query SQL server hostnamed pharos90-2008).
PRINT 'Pharos90-2008';
SELECT isc.ini_schema_name[Device], count(*) [Count]
FROM [pharos90-2008].pharos.dbo.edi_pharos_stations eps, [pharos90-2008].pharos.dbo.ini_schemas isc
WHERE eps.ini_schema_id = isc.ini_schema_id
GROUP BY isc.ini_schema_id, isc.ini_schema_name
As you can see, the query / code is exactly the same except for the fact that it is referencing a separate linked SQL Server (query being run from a central SQL Server Management Studio).
The ultimate goal is to output the queried data for each SQL instance to a single .txt file; format being, print the name of each particular SQL server followed by the corresponding queried data.
Any advice as to how one would accomplish such a task?
Thanks in advance.

Well, one way would be to create a cursor to iterate all of your linked servers. (You can find linked servers like this...)
SELECT * FROM sys.servers WHERE is_linked = 1
Then, you could use the undocumented sp_MSForEachDB stored procedure to run a dynamic version of your query (changing the server on each iteration) on each database in the cursor's current server. If you search for sp_MSForEachDB you can find plenty of information. But here's one link to save time.

Related

SSIS Automation

I came across a good SSIS and SQL Problem. How do I in SSIS create a package that will execute a SQL query in management studio and grab the results of that query (the query results are "Insert INTO statements") and run that insert into statement query results into another sql database within SSIS that updates a table in another server? (The first query runs in one database and the second query runs in a different database)
First of all, sql queries execute on the database, not management studio. Management studio is visual interface for configuring,managing and administer databases.
To me it doesn't sound like there's any problem here at all. Create one connection manager for each DB. Then create two "Execute SQL Tasks", put your insert statements in them use use your connection manangers you've created.
Run the first query in an Execute SQL task and store the results in a string variable.
Then run a second Execute SQL task, using the variable as your SQL command.
Create Connection Managers for each of the databases you need, your source and both (or all) destinations.
Create a Data Flow Task.
In your OLEDB Source, execute your SELECT statement.
Pump the results into a MultiCast Transformation. This allows you to send the exact same result set to multiple destinations.
Create a Destination for each table you want to write to, and connect them to the MultiCast.
Bob's your uncle.

sql server - Openquery vs 4part name

A view that references a remote server
4part name ([ServerName], [DatabaseName], [Owner], [Object Name]
OpenQuery
Which is better performance?
Why is performance good?
AFAIK, it depends a lot on your remote server type.
With recent SQL version (2016) on both server (local and remote), I didn't noticed any difference.
If your remote server is anything else (postgres, mysql...) your really should use OpenQuery as it executes the query on the remote server, getting only the correct resultset. If you use the 4 part name, SQL server will order and filter on local.
For example, take a 4 million record table and execute a query like :
SELECT * FROM reoteserver.database.schema.table where id = 4
With openquery, sql server will get only the record with id 4. Without, it will get all the table, and then filter it to get the id 4.
Late to the party here, but the difference essentially is that 4 part queries are executed locally, thus cannot utilise indexes or keys since the local server doesn't know about them. Instead it essentially retrieves the entire object, then applies the filter. On a small table, you would be unlikely to notice a difference, but on a table with millions of rows, you'd notice a difference. Openquery essentially tells the remote server to execute the query on it's behalf then pass the result back.
General rule I would say is;
NEVER join on to a table using 4 part. Only join using Openquery and I would even avoid that where possible, but that's more of a personal preference.
However, 4 part SP execution i.e. EXEC ServerName.DBName.SchemaName.ObjectName is essentially the same since that also tells the remote server to execute the query on its behalf.

Entity framework returning different result than SSMS

I've encountered quite a strange problem
I'm trying to run a stored procedure via entity framework to work out the counts of various people with a date of birth within a certain range
I'm running the following code
select count(*), groupId from app_people p
where p.DOB >= '2012-10-02'
and p.DOB <= '2013-10-01
group by groupId
The issue I'm getting is that the same stored procedure executed via ssms returns 70 whereas entity framework returns 59
I'm inserting the result of the above query into a temp table before updating an existing table with the results.
Any suggestions as to why this would be happening?
Both are being passed the same parameters.
Using the following code to execute the proc via Entity framework, the procedure has been imported from the database and is included in the datamodel.
DatabaseContext.TestProcedure(false);
This could be a permissions issue as HLGEM pointed out. If the connection to SQL Server in code uses a different login than your SQL Server Management Studio SSMS login (e.g. windows credentials) you may see different results.
You can use the following TSQL to execute a query from another security context within SSMS. You could do this to compare the results of the same query for different users.
-- Execute as another user: https://learn.microsoft.com/en-us/sql/t-sql/statements/execute-as-transact-sql
EXECUTE AS USER = 'testuser';
-- TSQL with inconsistent results between code and ssms.
SELECT COUNT(*), groupId FROM app_people;

For a Front end access user interface connected to a backend SQL server, do I create new queries for tables in the SQL server or Access frontend?

I am a new database intern working with a access front end and SQL server backend database. The database was custom made for the company. One of my assignments is to take scripts and apply them to make four new tables. I am aware that I need to make a new query for each new table but I don't know if I should make the query in SQL server management studio or the frontend access program. I have tried copying and pasting the given scripts into a new query in access but I get an error message "invalid SQL statement expected 'DELETE', 'INSERT'...". I decided to try to break done the program a little bit and tested the first line
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id =OBJECT_ID(N'[dbo] .[FK_tblInstrumentInterfaceLog_tlkpInstrument]') AND parent_object_id = OBJECT_ID(N'[dbo].[tblInstrumentInterfaceLog]'))
but the same error message keeps popping up. I even tried just SELECT * FROM sys.foreign_keys, and I got the error message "could not find file...". I am very much a beginner and any guidance would be appreciated.Basically am I supposed to be applying these scripts the server SQL database or on the front end access program?
Are you using a pass-through query? i.e. not just a select query. Access needs to know where to send the query and since you are using TSQL not Access SQL this needs to be executed on the server.
Normally when you query a linked table the information of how to get the data (the connection string) is tied to the table. But for this kind of query you'll probably need to tell Access explicitly. Unless you are using an ADP/ADE, then the connection info travels with the program not the table.
As a general rule, you use SQL management studio (SSMS) to create and run those scripts. So the general accepted approach here is such scripts will not be placed in the front end. As noted such scripts if for some reason must be placed in the front end, then you have to create them as pass-though, but EVEN in this case you want to use the SSMS to create such quires.
So the answer here is you create the new scripts and make table queries in the back end, or in this case using the SQL server management studio.
The syntax checking, query editor etc. in recent versions of SSMS now has auto-complete etc. and you can test/write/update those scripts in SQL server. Once you have such a query or even several of them, then the resulting “several” statements can be pasted into a front end query that been created as pass-though. If you do not use a pass-though query, then you are creating and using and assuming client side SQL (JET (now called ACE)).
The client side has it own version of SQL syntax, and it is NOT 100% compatible with the SERVER SIDE. If you writing SQL in the client that is NOT pass though, then you using a linked table to SQL server. These linked tables thus will use local (JET/ACE) based SQL queries. The ODBC driver thus translates this SQL into server side compatible syntax. However the JET/ACE sql syntax is very limited when compared to SQL server and no server side commands exist in this SQL syntax for the client data engine (JET/ACE)
So for many quires, you will and can simply build such queries using the Access query builder.
However for SQL that needs to run 100% server side then such quires has to be setup as pass-though and are in most cased built + tested using SSMS.

Excel query showing different result than SSMS query

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.