在C#中创建动态SQL存储过程然后选择它然后删除它

时间:2017-03-17 18:33:20

标签: c# sql-server stored-procedures sql-server-2012

嘿所有我想弄清楚如何解决这个问题。我想在我的C#程序中向查询发送一个参数,该参数是我的表的名称。我已经读过这是不可能的,他们建议您制作一个存储过程来执行此操作。

所以这是我目前的代码:

CREATE PROCEDURE _tmpSP 
@TableName NVARCHAR(128) 
AS 
BEGIN 
  SET NOCOUNT ON;
  DECLARE @Sql NVARCHAR(MAX);
SET @Sql = N'SELECT TOP 1 HelpMsg FROM ' + QUOTENAME(@TableName)
 EXECUTE sp_executesql @Sql
 DROP PROCEDURE [_tmpSP]
END

当我在Server Management Studio中执行它时,它会创建SP,但从不执行该存储过程,也不会将其删除。

当我在Server Management Studio中运行该SP时(右键单击 在可编程性> dbo._tmpSP 下并选择 >执行存储过程)并为其指定表名称,它会填充然后删除SP。这是我想要而不是必须进行2次查询的最终结果。

SP运行时的SQL查询是这个( tHelp 是表名):

USE [TTool]
GO    
DECLARE @return_value int    
EXEC    @return_value = [dbo].[_tmpSP]
        @TableName = N'tHelp'    
SELECT  'Return Value' = @return_value    
GO

我收到了返回的帮助消息,并返回了值0。

如何修改此SP才能执行此操作?

4 个答案:

答案 0 :(得分:1)

只需这样做,忘记存储过程:

private final void show() {
    loginSignupForm = new Form("Company", new BorderLayout());
    Tabs loginSignupTabs = new Tabs();
    Style loginSignupStyle = UIManager.getInstance().getComponentStyle("Tab");
    prepareAndAddSignupTab(loginSignupTabs, loginSignupStyle);
    prepareAndAddLoginTab(loginSignupTabs, loginSignupStyle);
    loginSignupForm.add(BorderLayout.CENTER, loginSignupTabs);
    loginSignupForm.show();
}

肮脏的C#......

EXECUTE sp_executesql 'SELECT TOP 1 HelpMsg FROM '+QUOTENAME(@TableName)

其中string qry = string.Format("SELECT TOP 1 HelpMSG FROM {0}", myTableName.Replace("'", "''")); cmd = conn.CreateCommand(); cmd.CommandText = qry; string helpMsg = conn.ExecuteScalar(); conn

的实例

答案 1 :(得分:0)

您需要创建另一个SP来应用您的逻辑。首先让我们看看你的SP:

CREATE PROCEDURE [_tmpSP]
@TableName NVARCHAR(128) 
AS 
 BEGIN 
  DECLARE @Sql NVARCHAR(MAX);
  SET @Sql = N'SELECT TOP 1 HelpMsg FROM ' + @TableName
  EXEC(@Sql)
END

然后,只有在返回结果后需要删除第一个SP时才创建另一个SP。逻辑将是:

Create procedure auto_delete
@NewTableName
as
begin

EXEC _tmpSP @TableName = @NewTableName

Drop procedure [_tmpSP]

End

在C#中(我假设你使用的是上面的第二个SP):

您的代码可能是这样的:

..
using System.Data.SqlClient;
..
string a = YourTableName;        
using (SqlConnection sqlCon = new SqlConnection(YourDatabaseConnection))
{
 sqlCon.Open()
using (SqlCommand sqlCmd = sqlCon.CreateCommand())
{
sqlCmd.CommandText = "auto_delete";
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.Add(new SqlParameter("NewTableName", a));
sqlCmd.ExecuteNonQuery();
}   
 sqlCon.Close();
 }

答案 2 :(得分:0)

我同意@SsJVasto。如果您仍然需要在C#程序中不对您的查询进行硬编码,则可以使用xml并将查询保留在其中。并获取xml并执行查询。我想你想处理一些动态的东西。

答案 3 :(得分:0)

这样做没有意义,因为它非常复杂,并且还会产生创建和删除存储过程的开销。如果您有一个动态查询来处理一些无法作为参数推送的动态元素,您可以构造查询字符串:

var query = $"SELECT TOP 1 col FROM {tableName}";

但是,如果基于用户输入构造tableName,则必须注意避免SQL注入。 This question and its answers处理这个问题:

DbConnection connection = GetMyConnection(); 
DbProviderFactory factory = DbProviderFactories.GetFactory(connection);
DbCommandBuilder commandBuilder = factory.CreateCommandBuilder();
var tableName commandBuilder.QuoteIdentifier(rawTableName);

如果需要“普通”(非表名)参数,请在查询中照常传递它们。例如。 @ param1,@ param2