How to safely pass variable to ADO.NET query without using parameter - sql-server

The problem is this - I'm usign SQL Server 2012 and I have 3 Linked IBM DB2 servers so I need to use OPENQUERY. However whe I tried to use :
command.Parameters.AddWithValue("#param", clientId);
I get error : an error occurred while preparing the query..
After some time of investigantion I figured out that if I use concrete value in my query instead of trying tu pass it with parameter everything was working fine, so I get to the conclusion that the problem is not in my query or more precisely maybe it's in the query but because I'm trying to use #param. The after further investigation I got this: OPENQUERY does not accept variables for its arguments. which I think seems to be the problem even though this is from year 2008 so the information is a little bit outdated.
However the best option would be to find a way to use parameters inside OPENQUERY but if that's really impossible in this scenarion what would be a save approach to pass the variable to my query?

As you found out, you cannot use parameters using OPENQUERY. Instead you could build up your SQL query and embed the values. So rather than this:
var sql = "select * from openquery(LinkedServer, 'SELECT * FROM MyTable WHERE tbl.ID = #param')";
You can do:
var someParameter = "SomeValue";
var rawQuery = "select * from openquery(LinkedServer, 'SELECT * FROM MyTable WHERE tbl.ID = ''{0}''')";
var sql = string.Format(rawQuery, someParameter);
However, you now need to be very careful of things like SQL injection.

Related

Can I pass parameter to a 2sxc SQL data source

Say that I have a large SQL table. I want to get specific data out of the table and into a 2sxc module.
SQL Query:
select * from myTable where dataCategory=
What I need to do is pass from the 2sxc module down into the data source.
Is that possible? The parameter will come to the module as a querystring value.
No problem :)
Use something like Select * from myTable where dataCategory = [QueryString:category]
You'll have to check if you need to wrap it in quotes like '[QueryString:category]' or without the quotes, I think it's without the quotes.
The sql data source even does additional parsing to ensure you're protected from SQL inject. So internally it actually converts it to a Select ... where dataCategory = #p1 and then tells the server that #p1 = 'cake' or whatever was in the url.

How can I pass a table name as a variable in SQL - Python 3.4

I am trying to write an SQL statement in python which passes a table name as a variable. However, I get the following error: Must declare the table variable "#P1".
pypyodbc.Programming Error: ('42000', '[42000]' [Miscrosoft] [SQL SERVER NATIVE CLIENT 10.0] [SQL SERVER] Must declare the table variable "#P1"
The code yielding the ERROR is:
query = cursor.execute('''SELECT * FROM ?''', (table_variable,))
I have other code where I pass variables to the SQL statement using the same syntax which works fine (code below works as intended).
query = cursor.execute('''SELECT column_name FROM information_schema.columns WHERE table_name = ?''', (table_variable,))
The error seems to occur when I am using a variable to pass a table name.
Any help resolving this error would be much appreciated.
With new comments from the OP this has changed rather significantly. If all you are trying to do is get a few rows of sample from each table you can easily leverage the sys.tables catalog view. This will create a select statement for every table in your database. If you have multiple schemas you could extend this to add the schema name too.
select 'select top 10 * from ' + QUOTENAME(t.name)
from sys.tables t
What you're trying to do is impossible. You can only pass values into queries as parameters - so
SELECT * FROM #Table
is banned but
SELECT * FROM TableName WHERE Column=#Value
is perfectly legal.
Now, as to why it's banned. From a logical point of view the database layer can't cache a query plan for what you're trying to do at all - the parameter will completely and utterly change where it goes and what returns - and can't guarantee in advance what it can or can't do. It's like trying to load an abstract source file at runtime and execute it - messy, unpredictable, unreliable and a potential security hole.
From a reliability point of view, please don't do
SELECT * FROM Table
either. It makes your code less readable because you can't see what's coming back where, but also less reliable because it could change without warning and break your application.
I know it can seem a long way round at first, but honestly - writing individual SELECT statements which specify the fields they actually want to bring back is a better way to do it. It'll also make your application run faster :-)
You can define a string variable:
table_var_str = 'Table_name'
st = 'SELECT * FROM ' + table_var_str
query = cursor.execute(st)
It will solve the problem.
You can also set the table_var_str as a list:
table_var_str = []
st = []
for i in range(N):
table_var_str.append = 'Table_name' + str(i)
st.append('SELECT * FROM ' + table_var_str[i])
for j in range(J):
query = cursor.execute(st[j])
If the query is very long, you should write them in a line instead of multi lines.

How can I query over all db of my server without looping over DB in pymssql connection

I'd like first to know how to make a query over all the databases in my server instance with pymssql (in MSSQL management studio = right click --> new query on the server thumbnail then don't need to specify the name of the db in the query - it just gives you one more column in the output which is the segment from which the record is from). Then how do you do the same as registered servers on two or multiple hosts (I have 2 hosts and I want to pass the same query do I really need to make the two connections ?)
thanks
You could use sp_foreachdb, like this:
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; EXEC update table set foo = bar'
Maybe this can help you (but - to be honest - I did not really understand what you want :-) )
SELECT * FROM sys.databases

SQL Server Linked Server Example Query

While in Management Studio, I am trying to run a query/do a join between two linked servers.
Is this a correct syntax using linked db servers:
select foo.id
from databaseserver1.db1.table1 foo,
databaseserver2.db1.table1 bar
where foo.name=bar.name
Basically, do you just preface the db server name to the db.table ?
The format should probably be:
<server>.<database>.<schema>.<table>
For example:
DatabaseServer1.db1.dbo.table1
Update: I know this is an old question and the answer I have is correct; however, I think any one else stumbling upon this should know a few things.
Namely, when querying against a linked server in a join situation the ENTIRE table from the linked server will likely be downloaded to the server the query is executing from in order to do the join operation. In the OP's case, both table1 from DB1 and table1 from DB2 will be transferred in their entirety to the server executing the query, presumably named DB3.
If you have large tables, this may result in an operation that takes a long time to execute. After all it is now constrained by network traffic speeds which is orders of magnitude slower than memory or even disk transfer speeds.
If possible, perform a single query against the remote server, without joining to a local table, to pull the data you need into a temp table. Then query off of that.
If that's not possible then you need to look at the various things that would cause SQL server to have to load the entire table locally. For example using GETDATE() or even certain joins. Others performance killers include not giving appropriate rights.
See http://thomaslarock.com/2013/05/top-3-performance-killers-for-linked-server-queries/ for some more info.
SELECT * FROM OPENQUERY([SERVER_NAME], 'SELECT * FROM DATABASE_NAME..TABLENAME')
This may help you.
For those having trouble with these other answers , try OPENQUERY
Example:
SELECT * FROM OPENQUERY([LinkedServer], 'select * from [DBName].[schema].[tablename]')
If you still find issue with <server>.<database>.<schema>.<table>
Enclose server name in []
You need to specify the schema/owner (dbo by default) as part of the reference. Also, it would be preferable to use the newer (ANSI-92) join style.
select foo.id
from databaseserver1.db1.dbo.table1 foo
inner join databaseserver2.db1.dbo.table1 bar
on foo.name = bar.name
select * from [Server].[database].[schema].[tablename]
This is the correct way to call.
Be sure to verify that the servers are linked before executing the query!
To check for linked servers call:
EXEC sys.sp_linkedservers
right click on a table and click script table as select
select name from drsql01.test.dbo.employee
drslq01 is servernmae --linked serer
test is database name
dbo is schema -default schema
employee is table name
I hope it helps to understand, how to execute query for linked server
Usually direct queries should not be used in case of linked server because it heavily use temp database of SQL server. At first step data is retrieved into temp DB then filtering occur. There are many threads about this. It is better to use open OPENQUERY because it passes SQL to the source linked server and then it return filtered results e.g.
SELECT *
FROM OPENQUERY(Linked_Server_Name , 'select * from TableName where ID = 500')
For what it's worth, I found the following syntax to work the best:
SELECT * FROM [LINKED_SERVER]...[TABLE]
I couldn't get the recommendations of others to work, using the database name. Additionally, this data source has no schema.
In sql-server(local) there are two ways to query data from a linked server(remote).
Distributed query (four part notation):
Might not work with all remote servers. If your remote server is MySQL then distributed query will not work.
Filters and joins might not work efficiently. If you have a simple query with WHERE clause, sql-server(local) might first fetch entire table from the remote server and then apply the WHERE clause locally. In case of large tables this is very inefficient since a lot of data will be moved from remote to local. However this is not always the case. If the local server has access to remote server's table statistics then it might be as efficient as using openquery More details
On the positive side T-SQL syntax will work.
SELECT * FROM [SERVER_NAME].[DATABASE_NAME].[SCHEMA_NAME].[TABLE_NAME]
OPENQUERY
This is basically a pass-through. The query is fully processed on the remote server thus will make use of index or any optimization on the remote server. Effectively reducing the amount of data transferred from the remote to local sql-server.
Minor drawback of this approach is that T-SQL syntax will not work if the remote server is anything other than sql-server.
SELECT * FROM OPENQUERY([SERVER_NAME], 'SELECT * FROM DATABASE_NAME.SCHEMA_NAME.TABLENAME')
Overall OPENQUERY seems like a much better option to use in majority of the cases.
I have done to find out the data type in the table at link_server using openquery and the results were successful.
SELECT * FROM OPENQUERY (LINKSERVERNAME, '
SELECT DATA_TYPE, COLUMN_NAME
FROM [DATABASENAME].INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME =''TABLENAME''
')
Its work for me
Following Query is work best.
Try this Query:
SELECT * FROM OPENQUERY([LINKED_SERVER_NAME], 'SELECT * FROM [DATABASE_NAME].[SCHEMA].[TABLE_NAME]')
It Very helps to link MySQL to MS SQL
PostgreSQL:
You must provide a database name in the Data Source DSN.
Run Management Studio as Administrator
You must omit the DBName from the query:
SELECT * FROM OPENQUERY([LinkedServer], 'select * from schema."tablename"')
For MariaDB (and so probably MySQL), attempting to specify the schema using the three-dot syntax did not work, resulting in the error "invalid use of schema or catalog". The following solution worked:
In SSMS, go to Server Objects > Linked Servers > Providers > MSDASQL
Ensure that "Dynamic parameter", "Level zero only", and "Allow inprocess" are all checked
You can then query any schema and table using the following syntax:
SELECT TOP 10 *
FROM LinkedServerName...[SchemaName.TableName]
Source: SELECT * FROM MySQL Linked Server using SQL Server without OpenQuery
Have you tried adding " around the first name?
like:
select foo.id
from "databaseserver1".db1.table1 foo,
"databaseserver2".db1.table1 bar
where foo.name=bar.name

Using Parameters in MS Reporting Services (SQL Server 2008) against an ODBC data source

I writing a report in Visual Studio that takes a user input parameter and runs against an ODBC datasource. I would like to write the query manually and have reporting services replace part of the where clause with the parameter value before sending it to the database. What seems to be happening is that the #parmName I am assuming will be replaced is actually being sent as part of the SQL statement. Am I missing a configuration setting somewhere or is this simply not possible?
I am not using the filter option in the tool because this appears to bring back the full dataset from the database and do the filtering on the SQL Server.
It sounds like you'll need to treat the SQL Statement as an expression. For example:
="Select col1, col2 from table 1 Where col3 = " & Parameters!Param1.Value
If the where clause is a string you would need to do the following:
="Select col1, col2 from table 1 Where col3 = '" & Parameters!Param1.Value & "'"
Important: Do not use line breaks in your SQL expression. If you do you will get an error.
Holla back if you need any more assistance.
Doesn't ODBC use the old "?" syntax for parameters? Try this:
select col1, col2 from table1 where col3 = ?
The order of your parameters becomes important then, but it's less vulnerable to SQL injection than simply appending the parameter value.
Encountered same problem trying to query an access database via ODBC.
My original query: SELECT A.1 FROM A WHERE A.1 = #parameter resulted in error. Altered to: SELECT A.1 FROM A WHERE A.1 = ?.
You then have to map the query parameter with your report parameter.
I am a bit confused about this question, if you are looking for simple parameter usage then the notation is :*paramName* , however if you want to structurally change the WHERE clause (as you might in sql+ using ?) then you should really be using custom code within the report to define a function that returns the required sql for the query.
Unfortunately, when using custom code, parameters cannot be referenced directly in the generated query but have to have there values concatenated into the resultant String, thus introducing the potential for SQL injection.

Resources