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 / 340413
Accepted
Geezer
Geezer
Asked: 2024-06-21 18:04:22 +0800 CST2024-06-21 18:04:22 +0800 CST 2024-06-21 18:04:22 +0800 CST

A visualização não reconhece uma alteração em uma tabela subjacente quando uma coluna existente é eliminada e substituída por outra com o mesmo nome, mas conforme computada

  • 772

Meu entendimento aqui é que quando uma View é criada, a definição é armazenada em metadados sys.tables. ou seja sys.views.

Além disso, se você usá SELECT * FROM-lo, armazenará os nomes exatos das colunas, por exemplo SELECT a, b FROM.

Mesmo se você usar a "CHECK OPTION" - ela ainda não será validada nas tabelas subjacentes.

"SCHEMABINDING", por outro lado, será validado nas tabelas subjacentes.

Meu problema é quando uma coluna em uma tabela é droppedsubstituída por outra com o mesmo nome, mas computedalgo estranho acontece quando você consulta uma visualização com base nessa tabela.

Aqui está um exemplo.

DROP TABLE IF EXISTS dbo.Test1;
DROP TABLE IF EXISTS dbo.Test2;
GO
CREATE TABLE dbo.Test1
(
    Id          INT IDENTITY(1,1) PRIMARY KEY ,
    Test1Col1   VARCHAR(80) NULL ,
    Test1Col2   VARCHAR(80) NULL ,
    Test1Col3   VARCHAR(80) NULL 
);
CREATE TABLE dbo.Test2
(
    Id          INT IDENTITY(1,1) PRIMARY KEY ,
    Test2Col1   VARCHAR(80) NULL ,
    Test2Col2   VARCHAR(80) NULL ,
    Test2Col3   VARCHAR(80) NULL ,
    Test1Id     INT 
);
GO
INSERT INTO dbo.Test1
    (Test1Col1, Test1Col2, Test1Col3)
VALUES 
    ('Test1Col1Data1', 'Test1Col2Data1', 'Test1Col3Data1') ,
    ('Test1Col1Data2', 'Test1Col2Data2', 'Test1Col3Data2') ,
    ('Test1Col1Data3', 'Test1Col2Data3', 'Test1Col3Data3') ;
GO
INSERT INTO dbo.Test2
    (Test2Col1, Test2Col2, Test2Col3, Test1Id)
VALUES 
    ('Test2Col1Data1', 'Test2Col2Data1', 'Test2Col3Data1', 1) ,
    ('Test2Col1Data2', 'Test2Col2Data2', 'Test2Col3Data2', 2) ,
    ('Test2Col1Data3', 'Test2Col2Data3', 'Test2Col3Data3', 3) ;
GO

Crie uma visualização baseada em tabelas.

CREATE OR ALTER 
    VIEW    dbo.View1 
AS

    SELECT T1.*, T2.*
    FROM    (
            SELECT  TestId = T.Id
            FROM    dbo.Test1   T
        )   T1
    INNER JOIN  dbo.Test2   T2  ON  T2.Test1Id = T1.TestId ;
GO
SELECT  * FROM dbo.View1 ;
GO

Você obtém este conjunto de resultados,

insira a descrição da imagem aqui

Agora eu ALTERmesa dbo.Test2.

DROPcoluna Test2Col3 e substituiu-a por uma computedcoluna com o mesmo nome.

ALTER TABLE dbo.Test2
    DROP COLUMN Test2Col3 ;
ALTER TABLE dbo.Test2
    ADD Test2Col3 AS Test2Col1;
GO

Agora, quando consulto a visualização, obtenho o seguinte conjunto de resultados.

SELECT  * FROM dbo.View1 ;
GO

insira a descrição da imagem aqui

Os dados em colunas Test2Col3pareciam Test1Idter deslocado 1 para a esquerda.

O que eu esperaria ver Test2Col3está sendo mostrado Test1Ide vice-versa.

insira a descrição da imagem aqui

Por que é isso?
Eu sei que uma atualização ou alteração da visualização corrigirá isso, mas os nomes das colunas não foram alterados. Eu repliquei isso no banco de dados SQL-2022 e Azure SQL.

sql-server
  • 3 3 respostas
  • 829 Views

3 respostas

  • Voted
  1. Peter Vandivier
    2024-06-22T03:23:51+08:002024-06-22T03:23:51+08:00

    Eu sei que uma atualização ou alteração da visualização corrigirá isso, mas os nomes das colunas não foram alterados. Velhote

    Você também não informou ao mecanismo quais colunas são importantes para você. Você disse select *.

    Já foi escrito longamente em outro lugar, mas TL; DR: "Não use select *".

    É um pouco mais complicado no exemplo do OP, mas modificando o exemplo de Martin , podemos ver que especificando as colunas por nome na definição da visualização, podemos pular os erros de ligação sem a necessidade de sp_refreshviewnotar a diferença...

    CREATE OR ALTER VIEW dbo.View1
      AS 
        SELECT * 
        FROM  dbo.Test;
    GO
    CREATE OR ALTER VIEW dbo.View2
      AS 
        SELECT A,B,Num 
        FROM  dbo.Test;
    

    Depois de fazer nosso drop-n-swap, select *cada uma dessas visualizações revela...

    Visualizar1

    A B Núm.
    B 10 C

    Visualizar2

    A B Núm.
    C B 10

    banco de dados<> violino

    • 10
  2. Best Answer
    Martin Smith
    2024-06-21T23:44:12+08:002024-06-21T23:44:12+08:00

    Quando você elimina e recria a coluna, a coluna é criada no final da tabela para que os resultados da SELECTconsulta subjacente tenham suas colunas deslocadas.

    SELECT T1.*, T2.*
    FROM    (
            SELECT  TestId = T.Id
            FROM    dbo.Test1   T
        )   T1
    INNER JOIN  dbo.Test2   T2  ON  T2.Test1Id = T1.TestId ;
    

    Os metadados da coluna para a visualização não são atualizados (conforme retornado por)

    SELECT * 
    FROM sys.columns 
    WHERE object_id = object_id('dbo.View1')
    

    O alias de coluna usado para as colunas retornadas da visualização é baseado nos ordinais das colunas da consulta subjacente e nas colunas definidas.

    Ele não os corresponde com base nos nomes definidos e nos nomes das colunas retornados pela consulta subjacente.

    Se a consulta subjacente retornar inesperadamente muitas colunas, as "extras" serão ignoradas e se retornar poucas, você receberá um erro

    A visualização ou função 'dbo.View1' tem mais nomes de colunas especificados do que colunas definidas.

    Um exemplo mais simples é

    DROP TABLE IF EXISTS dbo.Test;
    
    GO
    CREATE TABLE dbo.Test
    (
        A    CHAR(1) NOT NULL  ,
        B    CHAR(1) NOT NULL  ,
        Num  INT NOT NULL   
    );
    GO
    
    INSERT INTO dbo.Test(A, B, Num) VALUES ('A', 'B', 10);
    
    GO
    
    CREATE OR ALTER VIEW dbo.View1 AS SELECT * FROM  dbo.Test;
    
    GO
    
    ALTER TABLE dbo.Test DROP COLUMN A ;
    
    ALTER TABLE dbo.Test 
            ADD C CHAR(1) NOT NULL DEFAULT 'C',
                D CHAR(1) NOT NULL DEFAULT 'D';
    
    SELECT  * FROM dbo.View1
    
    

    O que retorna

    A B Núm.
    B 10 C

    É muito feliz alias Bas Ae Numas B. E para incluir a coluna recém-adicionada Cque possui o ordinal 3, é alias como Num(e claramente não é um int).

    A coluna Dé retornada pela SELECT *consulta subjacente, mas é "extra", portanto é ignorada. O plano de execução otimiza isso e essa coluna não está na lista de colunas de saída da tabela Test(ou mesmo presente na árvore de entrada ).

    • 9
  3. Zikato
    2024-06-21T19:07:36+08:002024-06-21T19:07:36+08:00

    sp_refreshview

    Atualiza os metadados para a visualização não vinculada ao esquema especificada. Os metadados persistentes de uma visualização podem ficar desatualizados devido a alterações nos objetos subjacentes dos quais a visualização depende.

    A seção Comentários continua (ênfase minha):

    Se uma visualização não for criada com SCHEMABINDING, sp_refreshview deverá ser executado quando forem feitas alterações nos objetos subjacentes à visualização, o que afeta a definição da visualização. Caso contrário, a visualização poderá produzir resultados inesperados quando for consultada.

    No seu caso

    exec sys.sp_refreshview @viewname = N'dbo.View1' 
    

    insira a descrição da imagem aqui

    • 1

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

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 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

    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
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • 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
    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

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