Temos um banco de dados SQL que é um banco de dados secundário ou devo dizer uma réplica secundária em um AlwaysOn Availabiltity Group. Como resultado, o banco de dados é sempre um banco de dados somente leitura e, portanto, não posso executar o procedimento armazenado abaixo porque o procedimento armazenado tenta criar uma nova tabela... basicamente, recebo a mensagem de erro:
Failed to update database xxxxxx because the database is read-only.
Foi sugerido que uma solução alternativa seria modificar o procedimento para SELECT ... INTO uma tabela em um banco de dados diferente (que não seja somente leitura/não faça parte de um AlwaysOn Availability Group) que esteja no mesmo servidor. Por exemplo:
INTO SomeOtherDatabase.' + QUOTENAME(@Domain) + '.' + QUOTENAME(@DeltaTable) + '
Alguém pode dar uma olhada no meu código e ajudar a modificá-lo?
Eu tentei o seguinte:
INTO tempdb.dbo.@DeltaTable' + QUOTENAME(@Domain) + '.' + QUOTENAME(@DeltaTable) + '
O procedimento acima não funcionou.
O procedimento completo é o seguinte:
CREATE PROCEDURE dbo.GenerateDeltaTable
@Domain VARCHAR(100),
@TableName VARCHAR(100),
@DeltaTable VARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX);
-- Construct dynamic SQL for dropping and creating the target table
SET @sql = '
IF OBJECT_ID(''' + QUOTENAME(@Domain) + '.' + QUOTENAME(@DeltaTable) + ''', ''U'') IS NOT NULL
DROP TABLE ' + QUOTENAME(@Domain) + '.' + QUOTENAME(@DeltaTable) + ';
SELECT T.*,
LOWER(CONVERT(VARCHAR(64), HASHBYTES(''SHA2_256'',
(SELECT T.* FOR JSON PATH, WITHOUT_ARRAY_WRAPPER, INCLUDE_NULL_VALUES)), 2)) AS signature
INTO ' + QUOTENAME(@Domain) + '.' + QUOTENAME(@DeltaTable) + '
FROM ' + QUOTENAME(@Domain) + '.' + QUOTENAME(@TableName) + ' AS T;';
-- Execute the constructed SQL
EXEC sp_executesql @sql;
END;
Alguma ideia sobre como criar a tabela do procedimento armazenado para outro banco de dados
só para sobreviver
Para deixar seu código funcional e bem lubrificado, fiz algumas alterações.
Isso deve levá-lo aonde você precisa ir. Há uma sintaxe alternativa onde você pode usar,
EXECUTE TargetDatabase.sys.sp_executesql
mas eu escolhi qualificar completamente as coisas nas referências de objeto.Localmente, posso executar isso repetidamente sem erros:
Que gera T-SQL parecido com este:
Não tenho um Grupo de Disponibilidade configurado, então, se houver mais erros relacionados a isso, caberá a você solucioná-los ou colocá-los em uma nova pergunta.