I've got an environment where my server is hosting a variable number of databases, all of which utilize the same table structures/schemas. I need to pull a sum of customers that meet a certain series of constraints with say, the user table. I also need to show which database I am showing the sum for.
I already know all I need to get the sum in a db by db query, but what I'm really looking to do is have one script that hits all of the non-system DBs currently on my server to grab this info.
Please forgive my ignorance in this, just starting out.
Update-
So, to clarify things somewhat; I'm using MS SQL 2014. I know how to pull a listing of the dbs I want to hit by using:
SELECT name
FROM sys.databases
WHERE name not in ('master', 'model', 'msdb', 'tempdb')
AND state = 0
And for the purposes of gathering the data I need from each, let's just say I've got something like:
select count(u.userid)
from users n
join UserAttributes ua on u.userid = ua.userid
where ua.status = 2
New Update:
So, I went ahead and added the ps sp_foreachdb as suggested by #Philip Kelley, and I'm now running into a problem when trying to run this (admittedly, I can tell I'm closer to a solution). So, this is what I'm using to call the sp:
USE [master]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[sp_foreachdb]
#command = N'select count(userid) as number from ?..users',
#print_dbname = 1,
#user_only = 1
SELECT 'Return Value' = #return_value
GO
This provides a nice and clean output showing a count, but what I'd like to see is the db name in addition to the count, something like this:
|[DB_NAME]|[COUNT]|
But for each DB
Is this even possible?
Source Code: https://codereview.stackexchange.com/questions/113063/executing-dynamic-sql-programmatically
Example Usage:
declare #options int = (
select a.ExcludeSystemDatabases
from dbo.ForEachDatabaseOptions() as a
);
execute dbo.usp_ForEachDatabase
#Command = N'print Db_Name();'
, #Options = #options;
#Command can be anything you want but obviously it needs to be a query that every single database can understand. #Options currently has 3 built-in settings but can be expanded however you see fit.
I wrote this to mimic/expand upon the master.sys.sp_MSforeachdb procedure but it could still use a little bit of polish (especially around the "logic" that replaces ? with the current database name).
Enumerate the databases from schema / sysdatabases. At least in situations without replication, excluding db_ids 1 to 4 as system databases should be reasonably robust:
SELECT [name] FROM master.dbo.sysdatabases WHERE dbid NOT IN (1,2,3,4)
Other methods exist, see here: Get list of databases from SQL Server and here: SQL Server: How to tell if a database is a system database?
Then prefix the query or stored procedure call with the database name, and in a cursor loop over the resultset of the first query, store that in a sysname variable to construct a series of statements like that:
SELECT column FROM databasename.schema.Viewname WHERE ...
and call that using the string execute function
EXECUTE('SELECT ... FROM '+##fully_qualified_table_name+' WHERE ...')
There’s the undocumented sytem procedure, sp_msForEachDB, as found in the master database. Many pundits on the internet recommend not using this, as under obscure fringe cases it can be unreliable and somehow skip random databases. Count me as one of them, this caused me serious grief a few months back.
You can write your own routine to provide this kind of functionality. This is a common task, however, and many people have already done it and posted their code online… so why re-invent the wheel?
#kittoes0124 posted a link to “usp_ForEachDatabse”. This probably works, though pro forma I hate any stored procedures that beings with usp_. I ended up with Aaron Bertrand’s utility, which can be found at http://www.mssqltips.com/sqlservertip/2201/making-a-more-reliable-and-flexible-spmsforeachdb/.
Install a version of this routine, figure out how it works, plug in your script, and go!
This question already has answers here:
Insert text with single quotes in PostgreSQL
(8 answers)
Closed 7 years ago.
When I am trying to find all records in details table which have Linux present in the array column operating_systems.
Query select * from details where 'Linux' = ANY(operating_systems); works perfectly and returns all records which have Linux in operating_systems column.
But if I want to get all records where I don't know is present in operating_systems I am unable to form a correct query.
Query select * from details where 'I don\'t know' = ANY(operating_systems); does not escape single quotes and takes it literally, resulting in an incomplete query.
Found that single quotes can be escaped by adding another single quote before it. So select count(*) from details where 'I don''t know' = ANY(operating_systems); works.
This is acceptable for ad-hoc queries, or queries where a data literal is hard coded.
It's absolutely not OK if the string comes from an application user. Do not do this. See http://bobby-tables.com/ for why.
Use parameterised queries (often incorrectly called prepared statements, though they're not quite the same thing). Exactly how to do that depends on your programming language and client, which you have not mentioned, but it usually involves "preparing" a statement then executing it with parameters.
Found that single quotes can be escaped by adding another single quote before it. So select count(*) from details where 'I don''t know' = ANY(operating_systems); works.
I asked a question yesterday about a procedure we're trying to re-write/optimize in our application. It's off of a search form with a bunch of criteria the user can specify. 40 parameters, 3 of which are long strings of Guids that I am passing into a UDF that returns a Table variable, all 3 of which we JOIN into our main FROM statement.
We did much of this query using Dynamic SQL, one of the main reasons we're re-writing the whole thing is because it's Dynamic SQL. Everything I ever read about Dynamic SQL is bad, especially for execution plans and optimization. Then I start coming across articles like these two....
Sometimes the Simplest Solution isn't the Best Solution
Erland Sommarskog - Dynamic SQL Conditions in T-SQL
I've always though Dynamic SQL was bad for security and optimization, we've tried removing it form our system wherever possible. Now we're restructuring the most executed query in our system (main search query) and we thought stripping all the Dynamic SQL was going to help.
Basically replacing
IF(#Param1 IS NULL)
#SQLString = #SQLString + " AND FieldX = #Param1"
...execute the #SQLString
with one large SQL block that has
WHERE (#Param1 IS NOT NULL AND FieldX = #Param1)
Reading those two articles it seems like this is going to work against me. I can't use RECOMPILE because we're in 2k5 still and even if we could this stored procedure is very high-use. Do I really want to write this Query in Dynamic SQL? How can it be faster if no execution plans can be stored?
I just saw this come up in our request logs. What were they trying to achieve?
The full request string is:
properties?page=2side1111111111111 UNION SELECT CHAR(45,120,49,45,81,45),CHAR(45,120,50,45,81,45),CHAR(45,120,51,45,81,45),CHAR(45,120,52,45,81,45),CHAR(45,120,53,45,81,45),CHAR(45,120,54,45,81,45),CHAR(45,120,55,45,81,45),CHAR(45,120,56,45,81,45),CHAR(45,120,57,45,81,45),CHAR(45,120,49,48,45,81,45),CHAR(45,120,49,49,45,81,45),CHAR(45,120,49,50,45,81,45),CHAR(45,120,49,51,45,81,45),CHAR(45,120,49,52,45,81,45),CHAR(45,120,49,53,45,81,45),CHAR(45,120,49,54,45,81,45) -- /*
Edit: As a google search didn't return anything useful I wanted to ask the question for people who encounter the same thing.
This is just a test for injection. If an attacker can see xQs in the output then they'll know injection is possible.
There is no "risk" from this particular query.
A developer should pay no attention to whatever injection mechanisms, formats or meanings - these are none of his business.
There is only one cause for for all the infinite number of injections - an improperly formatted query. As long as your queries are properly formatted then SQL injections are not possible. Focus on your queries rather than methods of SQL injection.
The Char() function interprets each value as an integer and returns a string based on given the characters by the code values of those integers. With Char(), NULL values are skipped. The function is used within Microsoft SQL Server, Sybase, and MySQL, while CHR() is used by RDBMSs.
SQL's Char() function comes in handy when (for example) addslashes() for PHP is used as a precautionary measure within the SQL query. Using Char() removes the need of quotation marks within the injected query.
An example of some PHP code vulnerable to an SQL injection using Char() would look similar to the following:
$uname = addslashes( $_GET['id'] );
$query = 'SELECT username FROM users WHERE id = ' . $id;
While addslashes() has been used, the script fails properly sanitize the input as there is no trailing quotation mark. This could be exploited using the following SQL injection string to load the /etc/passwd file:
Source: http://hakipedia.com/index.php/SQL_Injection#Char.28.29
I have a list of record Id's that I want to retrieve from Sql Server. I'm trying to figure out what the most performant way doing this would be. For example in code I have this:
var recordsToFind = new List<long>{ 12345, 12346, 45756, 42423 ... }
I want to create a stored proc that does this:
Select * From Puzzles where ID = {any of the integers passed in}
I know there are several options like, table value parameters, converting the list into a comma seperated string and using CharIndex, created a temp table and splitting the string etc...
What would be the best approach keeping in mind this will be used A LOT!
Thanks!
Several must read articles about this can be found here: http://www.sommarskog.se/arrays-in-sql.html Performance considerations are addressed in those articles.
Do you have the ability to change the code and the stored procedure or are you bound to some limit? If you have the ability to change both, I've seen this done before:
//Convert array/list to a comma delimited string using your own function (We'll call string strFilter)
//Pass strFilter into stored procedure (varchar(1000) maybe, we'll call parameter #SQLFILTER)
DECLARE #SQL AS VARCHAR(2000) --Or VARCHAR(MAX)
SET #SQL = "SELECT * FROM PUZZLES WHERE ID IN (" + #SQLFILTER + ")"
EXEC (#SQL)
I apologize if my syntax is off. My job unfortunately uses Oracle and I haven't used SQL Server a lot in 8 months. Hope this helps.
Micah,
is it out of the question to just do the simple sql 'in()' function?? (with obviously your array being used as a parameter, rather then the hardcoded values)
select * From Puzzles where ID in (12345, 12346, 45756, 42423)
maybe i've misunderstood the question mind you :)
[edit] - i notice that this is being used in .net. would it be possible to use linq against the database at all?? if so, then a few well crafted linq (over EF or subsonic for example) methods may do the trick. for example:
var idlist = new int[] { 12345, 12346, 45756, 42423 };
var puzzleids = Puzzles.Where(x =>
idlist.Contains(x.ID));