Pergunta

Se você configurar a coluna de uma tabela para ser uma coluna computada cuja fórmula chama uma função, torna -se uma dor mudar essa função subjacente. A cada alteração, você precisa encontrar todas as colunas cuja fórmula referencia a função, remova a referência, salve a tabela, altere a função, adicione tudo de volta e salve novamente. Até pequenas mudanças são pesadelos.

Você pode dizer ao SQL Server que não se importa que a função esteja sendo referenciada por fórmulas e apenas vá em frente e altere a função subjacente?

Detalhes adicionais: A coluna calculada não é persistida ou referenciada por uma restrição de FK porque não é determinística. A função leva em consideração o horário atual. Está lidando com a questão de saber se um registro expirou ou não.

Foi útil?

Solução

Não, até onde eu sei, você não pode fazer isso - você precisará primeiro remover todas as colunas computadas referenciando uma função, alterar a função e depois recriar as colunas computadas.

Talvez o MS nos dê um comando "Criar ou Alter Função" no SQL Server 2010/2011? :-)

Marc

Outras dicas

As consequências do alter pode ser enorme.

Você indexou as colunas? Usou -o em uma visão com esquemas? Persistiu? Relacionamento chave estrangeira com isso?

E se o alter for alterado no tipo de dados, anulabilidade ou determinismo?

É mais fácil parar a função alterar com dependências do que lidar com tantos cenários.

Desculpe por essa resposta tardia, mas pode ser útil.

Você pode usar uma função fictícia para cada coluna computada que chamará sua função real.

Exemplo:
A coluna computada usa a fórmula: dbo.link_comp ('123')
Esta função encaminhe os argumentos e chamadas e retorne a função dbo.link ('123') (sua função real)
Ambas as funções só precisam usar os mesmos argumentos e retornar o mesmo tipo.

Em seguida, a função bloqueada é dbo.link_comp e você ainda pode alterar o dbo.link.
Além disso, se sua função for chamada de outro SQL, você ainda poderá usar o nome da função real DBO.LINK, a função fictícia dbo.link_comp é apenas para a coluna computada.

Assuma a Tabela T1 com as colunas C1, C2, C3, C4, C5, onde C4 é uma coluna computada

Assume também a função de referências C4 Oldfunc, que você deseja ser substituído por newfunc

Primeiro, mova colunas não computadas de todas as linhas para uma tabela de temperatura

Select C1, C2, C3, C5 into TmpT1 from T1
Go

Em seguida, exclua todas as linhas de T1

Delete From T1
go

Agora você pode modificar a coluna C4

Alter table T1 alter column C4 as dbo.NewFunc()
Go

Agora coloque os dados salvos de volta na tabela original

Insert Into T1 (C1,C2,C3,C5) select C1,C2,C3,C5 from TmpT1

Agora exclua a tabela de temperatura

Drop Table TmpT1

Você pode tentar com uma boa ferramenta de comparação de esquema, que crie o script para você :)

Você pode alterar a coluna para não ser computada e atualizá-la por gatilho.

Ou você pode renomear a tabela para outra coisa, soltar a coluna computada e criar uma exibição no lugar da tabela original (ou seja, com o nome da tabela original) e incluindo a coluna "computado" que você precisa.

Editar: Observe que isso pode mexer com suas inserções no nome da tabela original (agora uma visualização). Obviamente, você pode manter a tabela antiga, soltar a coluna computada e criar uma visualização separada que continha a coluna computada.

Tivemos que contornar as colunas computadas o suficiente para ter decidido que são mais problemas do que ganham. Inserções de falhas (1), tentando inserir vistas em tabelas com colunas computadas, coisas que exigem mexer com o Set Arithabort e assim por diante.

(1) Temos inserções à prova de falhas como:

Insira no myTable Select * da Myothertable onde ...

que são projetados para falhar se uma nova coluna for adicionada uma tabela e não a outra. Com a coluna computada, precisamos nomear explicitamente todas as colunas, o que nos perde essa rede de segurança.

Sei que isso está atrasado para a festa, mas eu estava tendo o mesmo problema hoje e não encontrei nada que realmente resolva o problema, então eu rapidamente escrevi um.

Essencialmente, ele cria uma tabela temporária segurando as informações da coluna para cada coluna computada usando a função, solta as colunas das tabelas. Você atualiza sua função e deixa recriar todas as colunas novamente com suas definições.

Se você precisar fazer alterações nos parâmetros nas definições (como eu preciso), pode simplesmente scrip essa parte para onde as definições são criadas novamente.

Se você calculou colunas dentro de índices ou outras necessidades, poderá expandir facilmente o código, mas isso estava além do escopo das minhas necessidades.

Espero que possa ser útil para outra pessoa.

/* Create temporary table to hold definitions */
CREATE TABLE [#FUNCTION]
(
    [TABLE_NAME] nvarchar(255) NOT NULL,
    [COLUMN_NAME] nvarchar(255) NOT NULL,
    [DEFINITION] nvarchar(255) NOT NULL
)
GO

/* Add data to temp table */
INSERT INTO [#FUNCTION] ( [TABLE_NAME], [COLUMN_NAME], [DEFINITION] )
SELECT TABLE_NAME, COLUMN_NAME, definition FROM INFORMATION_SCHEMA.COLUMNS
INNER JOIN sys.computed_columns ON ( object_id = object_id( TABLE_NAME ) AND name = COLUMN_NAME )
WHERE definition LIKE '%MyFunctionName%'
GO

/* Remove columns */
DECLARE @TABLE_NAME nvarchar(255)
DECLARE @COLUMN_NAME nvarchar(255)

DECLARE c_CursorName CURSOR LOCAL FOR SELECT [TABLE_NAME], [COLUMN_NAME] FROM [#FUNCTION]
OPEN c_CursorName

FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC( 'ALTER TABLE [' + @TABLE_NAME + '] DROP COLUMN [' + @COLUMN_NAME + ']' )

    FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME
END

CLOSE c_CursorName
DEALLOCATE c_CursorName
GO

/* Update function */
-- Update function here
GO

/* Recreate computed columns */
DECLARE @TABLE_NAME nvarchar(255)
DECLARE @COLUMN_NAME nvarchar(255)
DECLARE @DEFINITION nvarchar(255)

DECLARE c_CursorName CURSOR LOCAL FOR SELECT [TABLE_NAME], [COLUMN_NAME], [DEFINITION] FROM [#FUNCTION]
OPEN c_CursorName

FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME, @DEFINITION

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC( 'ALTER TABLE [' + @TABLE_NAME + '] ADD [' + @COLUMN_NAME + '] AS ' + @DEFINITION )

    FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME, @DEFINITION
END

CLOSE c_CursorName
DEALLOCATE c_CursorName
GO

/* Remove temp table */
DROP TABLE [#FUNCTION]
GO
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top