AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 21046
Accepted
Taryn
Taryn
Asked: 2012-07-18 14:08:02 +0800 CST2012-07-18 14:08:02 +0800 CST 2012-07-18 14:08:02 +0800 CST

存储过程返回动态创建的表数据

  • 772

简短的背景故事,我们正在与拥有调查系统的外部供应商合作。当您创建新调查并且系统创建新表时,系统不一定设计得最好,即:

Tables
____
Library_1 -- table for Survey 1
SurveyId int
InstanceId int
Q_1 varchar(50)

Library_2 -- table for Survey 2
SurveyId int
InstanceId int
Q_2 int
Q_3 int
Q_4 varchar(255)

生成的表格SurveyId名称末尾带有 ( Library_),而生成的问题列QuestionId末尾带有 ( Q_)。 为了澄清,问题存储在一个单独的表中,因此虽然问题 ID 是连续的,但它们不会从每个调查的 1 开始。问题列将基于表中分配给它们的 id。

查询起来似乎很简单,除了我们需要从所有调查表中提取数据以发送到另一个系统,这就是问题所在。由于表是在前台添加新调查时自动创建的 -最终应用程序,其他系统无法处理这种类型的结构。他们需要数据保持一致才能使用。

因此,我的任务是编写一个存储过程,该过程将从所有调查表中提取数据并将其放置在以下格式中:

SurveyId    InstanceId    QNumber    Response
________    __________    _______    ________
1           1             1          great
1           2             1          the best
2           9             2          10
3           50            50         test

通过使所有表格的数据采用相同的格式,任何人都可以使用它,无论存在多少调查表格和问题。

我编写了一个似乎正在工作的存储过程,但我想知道我是否遗漏了什么,或者是否有更好的方法来处理这种情况。

我的代码:

declare @sql varchar(max) = ''
declare @RowCount int = 1
declare @TotalRecords int = (SELECT COUNT(*) FROM SurveyData)

Declare @TableName varchar(50) = ''
Declare @ColumnName varchar(50) = ''

WHILE @RowCount <= @TotalRecords
    BEGIN

        SELECT @TableName = tableName, @ColumnName = columnName
        FROM SurveyData
        WHERE @RowCount = rownum


        SET @sql = @sql + 
            ' SELECT s.SurveyId
                , s.InstanceId
                , CASE WHEN columnName = ''' +  @ColumnName + ''' THEN REPLACE(columnName, ''Q_'', '''') ELSE '''' END as QuestionNumber
                , Cast(s.' + @ColumnName + ' as varchar(1000)) as ''Response''
            FROM SurveyData t 
            INNER JOIN ' + @TableName + ' s' +
                ' ON REPLACE(t.tableName, ''Library_'', '''') = s.SurveyID ' +
            ' WHERE t.columnName = ''' + @ColumnName + ''''

        IF @RowCount != @TotalRecords
            BEGIN
                set @sql = @sql + ' UNION ALL'
            END

        SET @RowCount = @RowCount + 1       
    END


exec(@sql)

我用一些示例数据和代码 创建了一个SQL Fiddle 。

这种类型的查询应该以不同的方式编写吗?它有什么明显的问题吗?

不幸的是,这有很多未知数......我们将拥有多少张表格以及每次调查有多少问题。 我想说我们将进行 25-50 次调查,每个调查有 2-5 个问题。

sql-server sql-server-2008-r2
  • 1 1 个回答
  • 32501 Views

1 个回答

  • Voted
  1. Best Answer
    Taryn
    2012-07-26T05:56:59+08:002012-07-26T05:56:59+08:00

    根据聊天中人们的评论,我决定将我的脚本稍微更改为INSERT INTO一个临时表,而不是创建一条长 SQL 语句以在最后执行。所以最后我的存储过程包含以下内容:

    create table #SurveyData
    (
        tableName varchar(50),
        columnName varchar(50),
        columnId int,
        rownum int
    )
    
    create table #results
    (
        SurveyId int,
        InstanceId int,
        QuestionNumber int,
        Response varchar(1000)
    )
    
    -- insert the survey table structures for use
    insert into #SurveyData (tableName, columnName, columnId, rownum)
    select tables1.name, cols1.name, column_id, ROW_NUMBER() over(order by tables1.name, column_id)
    from sys.all_columns cols1
    inner join 
    (
        SELECT *
        FROM sys.all_objects
        WHERE type = 'U' 
        AND upper(name) like 'LIBRARY%' 
    ) Tables1
        ON cols1.object_id = tables1.object_id
    WHERE cols1.name Like 'Q_%'
    ORDER BY tables1.name, column_id;
    
    
    declare @sql varchar(max) = '';
    declare @RowCount int = 1;
    declare @TotalRecords int = (SELECT COUNT(*) FROM #SurveyData);
    
    Declare @TableName varchar(50) = '';
    Declare @ColumnName varchar(50) = '';
    
    WHILE @RowCount <= @TotalRecords
        BEGIN
    
            SELECT @TableName = tableName, @ColumnName = columnName
            FROM #SurveyData
            WHERE @RowCount = rownum
    
            SET @sql = 'INSERT INTO #results ' +
                        ' SELECT s.SurveyId
                            , s.InstanceId
                            , CASE WHEN columnName = ''' +  @ColumnName + ''' THEN REPLACE(columnName, ''Q_'', '''') ELSE '''' END as QuestionNumber
                            , Cast(s.' + @ColumnName + ' as varchar(1000)) as ''Response''
                        FROM #SurveyData t 
                        INNER JOIN ' + @TableName + ' s' +
                        ' ON REPLACE(t.tableName, ''Library_'', '''') = s.SurveyID ' +
                        ' WHERE t.columnName = ''' + @ColumnName + ''''
    
            exec(@sql)
    
            SET @RowCount = @RowCount + 1       
        END
    
        SELECT SurveyId, InstanceId, QuestionNumber, Response
        FROM #results
    
    drop table #SurveyData
    drop table #results
    

    请参阅带有最终脚本的SQL Fiddle

    • 2

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve