AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 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

Stored Procedure para retornar dados de tabela criados dinamicamente

  • 772

História rápida, estamos trabalhando com um fornecedor externo que possui um sistema de pesquisa. O sistema não é necessariamente o melhor quando você cria uma nova pesquisa e o sistema cria uma nova tabela, ou seja:

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)

As tabelas são geradas com o SurveyIdno final do nome ( Library_) e as colunas Question são geradas com o QuestionIdno final ( Q_). Para esclarecer, as perguntas são armazenadas em uma tabela separada para que, embora os IDs das perguntas sejam sequenciais, eles não comecem em 1 para cada pesquisa. As colunas de perguntas serão baseadas no id atribuído a elas na tabela.

Parece simples o suficiente para consultar, exceto que precisamos extrair os dados de todas as tabelas de pesquisa para serem enviadas para outro sistema e é aí que entra o problema. Já que as tabelas são criadas automaticamente quando uma nova pesquisa é adicionada pelo front- aplicação final, o outro sistema não pode lidar com esse tipo de estrutura. Eles precisam que os dados sejam consistentes para serem consumidos.

Então, fui encarregado de escrever um procedimento armazenado que extrairá os dados de todas as tabelas do Survey e os colocará no seguinte formato:

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

Ao ter os dados de todas as tabelas no mesmo formato, eles podem ser consumidos por qualquer pessoa, não importa quantas tabelas e perguntas de pesquisa existam.

Eu escrevi um procedimento armazenado que parece estar funcionando, mas estou me perguntando se estou faltando alguma coisa ou se há uma maneira melhor de lidar com esse tipo de situação.

Meu código:

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)

Eu criei um SQL Fiddle com alguns dados de exemplo e o código.

Existe uma maneira diferente de escrever esse tipo de consulta? Há algum problema perceptível com ele?

Infelizmente, há muitas incógnitas com isso... quantas mesas teremos e quantas perguntas por pesquisa. Eu diria que teremos entre 25 a 50 pesquisas, com 2 a 5 perguntas cada.

sql-server sql-server-2008-r2
  • 1 1 respostas
  • 32501 Views

1 respostas

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

    Com base nos comentários das pessoas no chat, decidi alterar um pouco meu script para INSERT INTOuma tabela temporária em vez de criar uma instrução SQL longa para executar no final. Então, no final, meu procedimento armazenado contém o seguinte:

    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
    

    Veja SQL Fiddle com o script final

    • 2

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST

Hot tag

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

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve