【问题标题】:SQL: How to make table name in stored procedure dynamicSQL:如何使存储过程中的表名动态化
【发布时间】:2014-10-10 00:42:44
【问题描述】:

我对 SQL Server 很陌生,希望这里有人可以帮助我(我使用的是 QL Server 2008)。

以下是一个按预期工作的小程序。

现在我想使用相同的过程来更新多个表,因为所有这些表都具有完全相同的列名和列格式,唯一的区别是我在下面添加了XXX 的表名的第二部分。

有人可以告诉我如何将其变为动态的,并为此提供一些解释吗? 我不能在这里提供更多,因为我不确定如何处理这个问题——除了可能声明@sql nvarchar(max) 并在执行之前将整个查询包装在SET @sql = N'...' 中。

我的存储过程:

    CREATE PROCEDURE [dbo].[Cal_UpdateTeam]
        @team nvarchar(100),
        @teamID int,
        @notes nvarchar(1000),
        @log nvarchar(100),
        @admin varchar(50)
    AS
    BEGIN
        SET NOCOUNT ON;

        BEGIN   

        IF NOT EXISTS 
        (
                SELECT  * 
                FROM    Cal_XXX
                WHERE   teamID = @teamID
        )
        INSERT INTO Cal_XXX
        (
                team,
                teamID,
                notes,
                log,
                admin
        )
        SELECT  @team,
                @teamID,
                @notes,
                @log,
                @admin
        ELSE
                UPDATE  Cal_XXX
                SET     team = @team,
                        teamID = @teamID,
                        notes = @notes,
                        log = @log,
                        admin = @admin
                WHERE   teamID = @teamID

        END
END

非常感谢 Mike 提供的任何提示和建议。

【问题讨论】:

  • “所有这些表都具有完全相同的列名和列格式”。这通常是糟糕的数据库设计的标志。你应该有一个表,用一列来区分“XXX”。例如,如果你有一个好的设计,那么你就不会为这个存储过程而苦恼。
  • @GordonLinoff:谢谢。是的,它们都具有相同的列名,但其中一些具有我的查询不需要的其他列。
  • @Mike:公共属性应该在一个公共表中;具体属性应该在子类型表中。
  • 谢谢,两位。我不确定将此处的所有表格组合在一起是否有意义,因为这些表格用于生成导航栏,其中导航栏的每个级别都有自己的表格,并且它们相互链接,因为每个级别都有下一级的子级。如果我将它们组合起来,那么链接将在同一个表中。

标签: sql sql-server stored-procedures dynamic


【解决方案1】:

您应该将您的 sql 查询包装在一个 nvarchar 中,然后执行该查询,如下例所示:

    declare @sql nvarchar(max)
    declare @TableName nvarchar(max)
    set @TableName = 'mytable'
    set @sql = 'Select * from ' + @TableName
    Exec sp_executesql @sql

【讨论】:

  • 这对我有用。这应该被标记为接受的答案。
【解决方案2】:

在 SP 中,您可以使用临时表,例如:

CREATE PROCEDURE SELECT_TABLE
    @REQUEST_ID INT
AS
BEGIN

/*************************************
** Temporary table                  **
*************************************/
    CREATE TABLE #SOURCE (
        ID        INT
      , ID_PARENT INT
      , NAME      VARCHAR(200)
      , SORT      INT
      ..
      ..
    )

IF @REQUEST_ID = 'YES' BEGIN
    INSERT INTO #SOURCE SELECT * FROM SOURCE_A
END
ELSE BEGIN
    INSERT INTO #SOURCE SELECT * FROM SOURCE_B
END

SELECT * FROM #SOURCE
.....


END

GO

在 SP 中,您可以封装其他具有不同表名的 SP,如参数:

CREATE PROCEDURE SELECT_FROM_TABLE_A
AS
BEGIN
    SELECT * FROM SOURCE_A
END
GO
CREATE PROCEDURE SELECT_FROM_TABLE_B
AS
BEGIN
    SELECT * FROM SOURCE_B
END
GO

CREATE PROCEDURE SELECT_TABLE
    @REQUEST_ID INT

AS
BEGIN

/**********************************************
** Subrequest select                         **
**********************************************/

    IF @REQUEST_ID = 'YES' BEGIN
        -- Request SP fro Source A
        EXEC SELECT_FROM_TABLE_A
    END
    ELSE
    BEGIN
        -- Request SP fro Source B
        EXEC SELECT_FROM_TABLE_B
    END
END
GO

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 2017-01-26
    • 2012-10-26
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多