Pregunta

Si configura la columna de una tabla a ser una columna calculada cuya fórmula llama a una función, se convierte en un dolor de cambiar esa función subyacente. Con cada cambio, usted tiene que encontrar todas las columnas cuya única fórmula que hace referencia la función, quite la referencia, guardar la tabla, alterar la función, añadir todo de nuevo, y guardar de nuevo. Incluso los pequeños cambios son pesadillas.

Se puede decir de SQL Server que no le importa que la función está siendo referenciado por las fórmulas y simplemente seguir adelante y cambiar la función subyacente?

Detalles adicionales: La columna calculada no se conserva o se hace referencia por una restricción FK porque es no determinista. La función toma en consideración el tiempo actual. Se trata de la cuestión de si un registro ha expirado o no.

¿Fue útil?

Solución

No, por lo que yo sé, no se puede hacer esto - que tendrá que eliminar primero todas las columnas calculadas que hacen referencia a una función, alterar la función, y volver a crear las columnas calculadas

.

Tal vez MS nos dará un comando "CREATE o ALTER FUNCTION" en SQL Server 2010/2011? : -)

Marc

Otros consejos

Las consecuencias de la ALTER podrían ser enormes.

¿Usted ha indexado las columnas? Se utiliza en una vista con SCHEMABINDING? Persistido él? Extranjera relación clave a ella?

¿Qué pasa si el ALTER cambia el tipo de datos, nulabilidad o el determinismo?

Es más fácil dejar de alterar la función de las dependencias de tratar con tantos escenarios.

Lo siento por esta respuesta tardía, pero puede ser útil.

Puede utilizar una función ficticia para cada columna calculada que llame a su función real.

  

Ejemplo:
  La columna calculada utilizar la fórmula: dbo.link_comp ( '123')
  Esta función transmita los argumentos y las llamadas y volver a la función dbo.link ( '123') (Su función real)
  Ambas funciones sólo tiene que utilizar los mismos argumentos y devolver el mismo tipo.

A continuación, la función que está bloqueado es dbo.link_comp y todavía se puede alterar dbo.link.
Además, si su función es llamada desde otra SQL, puede seguir utilizando su nombre de función real dbo.link, la dbo.link_comp función ficticia es sólo para la columna calculada.

Supongamos tabla T1 con columnas C1, C2, C3, C4, C5, donde C4 es una columna calculada

También asumirá la función de referencias del C4 OldFunc que desea ser reemplazado por NewFunc

En primer lugar, mover columnas no calculadas, desde todas las filas de una tabla temporal

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

A continuación, elimine todas las filas de T1

Delete From T1
go

Ahora puede modificar la columna C4

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

Ahora pon los datos guardados en la tabla original

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

Ahora Eliminar la tabla temporal

Drop Table TmpT1

Usted podría tratar con un buen esquema de herramienta de comparación, que crean el guión para usted:)

Se puede cambiar la columna a no computada, y actualizarlo por trigger.

O puede cambiar el nombre de la tabla a otra cosa, la caída de la columna calculada, y crear una vista en lugar de la tabla original (es decir, con el nombre de la tabla original) y que incluye la columna "computarizada" que necesita.

EDIT: Nótese que esto puede meterse con sus inserta en el nombre de tabla original (ahora una vista). Obviamente se podía mantener la mesa de edad, la caída de la columna calculada, y crear una vista separada que contenía la columna calculada.

Hemos tenido que trabajar alrededor de las columnas calculadas veces suficientes como para haber decidido que son más problemas de lo que ganan. Fail-saf inserciones (1), tratando de insertar en vistas a las tablas con columnas calculadas, cosas que requieren jugar con ARITHABORT SET y así sucesivamente.

(1) Tenemos a prueba de fallos insertos como:

INSERT INTO MiTabla SELECT * FROM MyOtherTable DONDE ...

que están diseñados para fallar si una nueva columna se añade una tabla y no el otro. Con columna calculada tenemos que mencionar explícitamente todas las columnas, lo que nos pierde esa red de seguridad.

Sé que es tarde a la fiesta, pero yo estaba teniendo este mismo problema hoy y no encontró nada que en realidad se resuelve el problema así que rápidamente con guión uno.

En esencia, se crea una tabla temporal que sostiene la información de la columna para cada columna calculada usando la función, gotas para las columnas de las tablas. A continuación, actualice su función y deja que recrear todas las columnas de nuevo con sus definiciones.

Si tiene que realizar cambios en los parámetros dentro de las definiciones (que necesito) puede simplemente script que parte en donde las definiciones son creados de nuevo.

Si ha calculado columnas dentro de los índices u otras necesidades se puede ampliar fácilmente en el código, pero esto fue más allá del alcance de mis necesidades.

Espero que pueda ser útil a alguien más.

/* 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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top