我有一个C#程序,它使用OPENQUERY()
从链接服务器中进行选择。此传递查询接受参数。为了防止SQL注入,我想以类似于SqlCommand.Parameters.AddWithValue
的方式传递此参数,但是OPENQUERY()
不接受变量。
到目前为止,我一直在使用SqlCommand将参数传递给针对SQL Server中的表运行的查询。但是我还需要访问Oracle的链接服务器。是否有任何方法可以添加此参数而不将其连接为字符串?
string query = "SELECT * FROM OPENQUERY(linked_server,
'SELECT * FROM User.Table WHERE col1 = @parameter1 ')";
编辑: 我没有权限在远程Oracle服务器上创建存储过程。因此,对存储过程执行Sp_executesql似乎不是我的直接答案。
答案 0 :(得分:6)
特别针对链接服务器进行EXEC
调用(请参阅docs):
EXEC( 'SELECT * FROM User.Table WHERE col1 = ?', '<param>' ) AT linked_server
您可以将所有内容放在string query
中,并且您可以安全地从SQL SELECT
语句注入,尽管您可能会收到EXEC
语句的语法错误。
答案 1 :(得分:1)
从性能角度来看,这不是最佳方法,但您可以在SQL Server
方进行过滤:
string query = "SELECT *
FROM OPENQUERY(linked_server, 'SELECT * FROM User.Table') s
WHERE col1 = @parameter1";
修改强>
来自How to pass a variable to a linked server query:
查询链接服务器时,经常执行使用OPENQUERY,OPENROWSET或OPENDATASOURCE语句的传递查询。
本文提供了三个如何将变量传递给链接服务器查询的示例。
要将变量传递给其中一个传递函数,您必须构建动态查询。
方法1:
传递基本值
当已知基本的Transact-SQL语句,但您必须传入一个或多个特定值时,请使用与以下示例类似的代码:
DECLARE @TSQL varchar(8000), @VAR char(2)
SELECT @VAR = 'CA'
SELECT @TSQL = 'SELECT * FROM OPENQUERY(MyLinkedServer
,''SELECT * FROM pubs.dbo.authors WHERE state = '''''
+ @VAR + ''''''')'
EXEC (@TSQL)
方法2:
使用Sp_executesql存储过程
要避免使用多层引号,请使用与以下示例类似的代码:
DECLARE @VAR char(2)
SELECT @VAR = 'CA'
EXEC MyLinkedServer.master.dbo.sp_executesql
N'SELECT * FROM pubs.dbo.authors WHERE state = @state',
N'@state char(2)',
@VAR
并在您的示例中:
DECLARE @parameter1 <your_type> = ?;
EXEC linked_server.master.dbo.sp_executesql
@'SELECT * FROM User.Table WHERE col1 = @parameter1 '
,N'@parameter1 <your_type>'
,@parameter1;
如果您需要在本地进行其他操作:
DECLARE @parameter1 <your_type> = ?;
CREATE #temp(col_name <type>, ...);
INSERT INTO #temp(col_name)
EXEC linked_server.master.dbo.sp_executesql
@'SELECT col_name1,... FROM User.Table WHERE col1 = @parameter1 '
,N'@parameter1 <your_type>'
,@parameter1;
SELECT *
FROM #temp
-- JOIN any local table (SQL Server's side)
-- WHERE any_condition;
答案 2 :(得分:1)
为了能够获得一些SQL服务器查询兑现,最好使用sp_executesql存储过程。
设计喜欢将参数传递给查询,有利于安全性(SQL注入防护)以及需要考虑implied conversions时的性能(真正的性能杀手)
你可以像调用
一样简单using (SqlCommand cmd = _con.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_executesql";
cmd.Parameters.Add("sel_query", myQuery);
return cmd.ExecuteReader();
}
myQuery变量可以包含任何有效的TSQL,并且可以像您一样复杂。只需确保您的服务器以及您要连接的服务器的目的和安全性。
谷歌搜索时可以找到一些动态样本,请查看this example
然而,您可能会退后一步,喝咖啡思考,也许您想将其他服务器表定义与代码分离。
您可以考虑在服务器中生成查询链接服务器的视图,然后您只需查询本地对象,也可以在存储过程和函数上正常工作。
解耦还允许您查询客户端没有驱动程序的其他数据库。我已经使用这种方法在DB2,Oracle等上创建了这样的视图,而无需在客户端系统上安装驱动程序。
希望有所帮助。
快乐编码
沃尔特
答案 3 :(得分:0)
以下是创建动态查询并执行它的最佳示例。 https://www.codeproject.com/Articles/20815/Building-Dynamic-SQL-In-a-Stored-Procedure。我认为它可以帮助你。