如何将参数传递给c#中的传递查询?

时间:2018-04-19 23:01:28

标签: c# sql-server oracle openquery

我有一个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似乎不是我的直接答案。

4 个答案:

答案 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。我认为它可以帮助你。