Resolvendo o erro “Procedure or function sp_attach_db has too many arguments specified” no SQL Server

0Comments

Esse erro do SQL Server ocorre quando passamos muitos parâmetros ao realizar um attach de uma base a uma instância do SQL Server 2005/2008/2008 R2. Por limitação da procedure sp_attach_db não é possível realizar attach de mais de 16 datafiles (incluindo o log). Veja como resolver!

Realizar o attach de uma base se torna uma ação comum no dia-a-dia de um DBA SQL Server, porém, quando é necessário fazer essa tarefa em uma base que possui muitos datafiles pode gerar uma certa dor cabeça!

A procedure sp_attach_db possui algumas limitações, dentre elas o fato de não aceitar mais de 16 datafiles (incluindo o logfile) como parâmetros a serem anexados ao banco, gerando o erro “Procedure or function sp_attach_db has too many arguments specified”.

A maneira correta de resolver este erro é usando o comando CREATE DATABASEFOR ATTACH. Este comando substituirá a procedure sp_attach_db que entrará em desuso futuramente.

Vamos simular o problema criando uma base com 16 datafiles + 1 logfile com 5mb cada, gerando uma base de 85mb:

1 – Criando o banco de dados

-- Cria a base com 16 datafiles e 1 logfile de 5mb cada
CREATE DATABASE [DatabaseTest] 
 ON PRIMARY 
  ( NAME = 'DatabaseTest01', FILENAME = 'C:\DatabaseTest\DatabaseTest01.mdf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest02', FILENAME = 'C:\DatabaseTest\DatabaseTest02.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest03', FILENAME = 'C:\DatabaseTest\DatabaseTest03.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest04', FILENAME = 'C:\DatabaseTest\DatabaseTest04.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest05', FILENAME = 'C:\DatabaseTest\DatabaseTest05.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest06', FILENAME = 'C:\DatabaseTest\DatabaseTest06.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest07', FILENAME = 'C:\DatabaseTest\DatabaseTest07.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest08', FILENAME = 'C:\DatabaseTest\DatabaseTest08.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest09', FILENAME = 'C:\DatabaseTest\DatabaseTest09.ndf' , SIZE = 5120KB),
  ( NAME = 'DatabaseTest10', FILENAME = 'C:\DatabaseTest\DatabaseTest10.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest11', FILENAME = 'C:\DatabaseTest\DatabaseTest11.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest12', FILENAME = 'C:\DatabaseTest\DatabaseTest12.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest13', FILENAME = 'C:\DatabaseTest\DatabaseTest13.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest14', FILENAME = 'C:\DatabaseTest\DatabaseTest14.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest15', FILENAME = 'C:\DatabaseTest\DatabaseTest15.ndf' , SIZE = 5120KB), 
  ( NAME = 'DatabaseTest16', FILENAME = 'C:\DatabaseTest\DatabaseTest16.ndf' , SIZE = 5120KB)
 LOG ON 
  ( NAME = 'DatabaseTest_log', FILENAME = 'C:\DatabaseTest\DatabaseTest_log.ldf' , SIZE = 5120KB)
GO

2 – Realizando o dettach do banco

USE [master]
GO
 
ALTER DATABASE [DatabaseTest] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
 
EXEC master..sp_detach_db @dbname = 'DatabaseTest'
GO

3 – Tentando incluir o banco usando a procedure sp_attach_db

EXEC sp_attach_db 'DatabaseTest', 
  'C:\DatabaseTest\DatabaseTest01.mdf', 
  'C:\DatabaseTest\DatabaseTest02.ndf',
  'C:\DatabaseTest\DatabaseTest03.ndf',
  'C:\DatabaseTest\DatabaseTest04.ndf',
  'C:\DatabaseTest\DatabaseTest05.ndf',
  'C:\DatabaseTest\DatabaseTest06.ndf',
  'C:\DatabaseTest\DatabaseTest07.ndf',
  'C:\DatabaseTest\DatabaseTest08.ndf',
  'C:\DatabaseTest\DatabaseTest09.ndf',
  'C:\DatabaseTest\DatabaseTest10.ndf',
  'C:\DatabaseTest\DatabaseTest11.ndf',
  'C:\DatabaseTest\DatabaseTest12.ndf',
  'C:\DatabaseTest\DatabaseTest13.ndf',
  'C:\DatabaseTest\DatabaseTest14.ndf',
  'C:\DatabaseTest\DatabaseTest15.ndf',
  'C:\DatabaseTest\DatabaseTest16.ndf',
  'C:\DatabaseTest\DatabaseTest_log.ldf'
GO

Ao tentar incluir a base retornará o erro abaixo:
Msg 8144, Level 16, State 2, Procedure sp_attach_db, Line 0
Procedure or function sp_attach_db has too many arguments specified.

4 – Incluindo o banco usando o comando CREATE DATABASE … FOR ATTACH

Sendo assim, a única maneira de incluir a base é utilizando o comando CREATE DATABASE … FOR ATTACH:

CREATE DATABASE [DatabaseTest] ON
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest01.mdf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest02.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest03.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest04.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest05.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest06.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest07.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest08.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest09.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest10.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest11.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest12.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest13.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest14.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest15.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest16.ndf' ),
  ( FILENAME = 'C:\DatabaseTest\DatabaseTest_log.ldf' )
FOR ATTACH
GO

Dessa forma conseguimos incluir a base sem problemas, considerando que todos os caminhos do banco estejam corretos e não tenha esquecido nenhum deles:
Command(s) completed successfully.

Uma informação importante sobre o FOR ATTACH é que quando especificado no CREATE DATABASE a base criada herda todas as configurações e propriedades da base original.

Outra observação a ser considerada é que a procedure sp_attach_db será descontinuada conforme a documentação da própria Microsoft.

Tags:, , , ,