Home > Mobile >  SQL Server Restore Verify Only Loop with Update
SQL Server Restore Verify Only Loop with Update

Time:06-11

I'm running a Restore Verify Only loop through a table, but I need it to UPDATE a field in that table if it's successful. Here is my code:

DECLARE @Path NVARCHAR(max)
DECLARE @DatabaseName NVARCHAR(100)
DECLARE @NSql NVARCHAR(1000)
DECLARE @Update NVARCHAR(200)
DECLARE @DB_Text NVARCHAR(50)= 'Backup has been confirmed for'

BEGIN
DECLARE
     @DatabaseId INT = 1,
     @NumberOfDBs INT
SELECT  @NumberOfDBs= COUNT(*) FROM dbo.RestoreVerifyDatabases
WHILE @DatabaseId<=  @NumberOfDBs
BEGIN
    SELECT * FROM dbo.RestoreVerifyDatabases WHERE DatabaseId=  @DatabaseId         
    SET  @DatabaseId = @DatabaseId   1
END


SET @Path = (SELECT LastBackupFileName FROM RestoreVerifyDatabases WHERE DatabaseId = 
@DatabaseId)
SET @DatabaseName = (SELECT DatabaseName FROM RestoreVerifyDatabases WHERE DatabaseId = 
@DatabaseId)

SET @NSql = N'SELECT LastBackupFileName
FROM RestoreVerifyDatabases 
WHERE DatabaseName = @DatabaseName
AND DatabaseId = @DatabaseId'

EXEC sp_executesql @NSql

IF @DatabaseId IS NULL
    BEGIN 
         RAISERROR(N'Verify failed. Backup information for database N''@DatabaseName'' not 
 found.', 16, 1) 
    END

RESTORE VERIFYONLY 
FROM @Path
WITH FILE = @DatabaseId,  checksum

SET @Update= N'UPDATE RestoreVerifyDatabases
SET Confirmed = @DB_Text   @DatabaseName
WHERE DatabaseID = @DatabaseId'

EXEC sp_executesql @Update

END

The looping and calling of Restore Verify Only works fine but the UPDATE is not getting called. I've fought with this problem for days now, please help.

CodePudding user response:

There's a few things wrong with your code as far as I can see. As my comment indicated, you run a loop over the @databaseID, and then immediately increase the id with 1 within the loop.

This means your @databaseId simply will increase until it reaches the maximum value of the id, and then exits the loop. The rest of your code will then execute once (only for that ID).

That happens here in your code:

SELECT  @NumberOfDBs= COUNT(*) FROM dbo.RestoreVerifyDatabases
WHILE @DatabaseId<=  @NumberOfDBs
BEGIN
    SELECT * FROM dbo.RestoreVerifyDatabases WHERE DatabaseId=  @DatabaseId         
    SET  @DatabaseId = @DatabaseId   1
END

-- Bunch of other code

So @databaseID goes from 1 to 50 (just a random number) within that loop, then exists with a value of 50. None of the underlying code ever gets to see any value other than 50.

To fix that, the code should look like this:

SELECT  @NumberOfDBs= COUNT(*) FROM dbo.RestoreVerifyDatabases
WHILE @DatabaseId<=  @NumberOfDBs
BEGIN
    SELECT * FROM dbo.RestoreVerifyDatabases WHERE DatabaseId=  @DatabaseId         

    -- Bunch of other code
    SET  @DatabaseId = @DatabaseId   1
END

This would ensure the "bunch of other code" processes @databaseid = 1, then processes @databaseid = 2, etc. until @databaseid = 50.

You can also remove this line:

SELECT * FROM dbo.RestoreVerifyDatabases WHERE DatabaseId=  @DatabaseId  

I suspect you have it for debugging purposes, but it doesn't really do anything.

These lines can be simplified:

SET @Path = (SELECT LastBackupFileName FROM RestoreVerifyDatabases WHERE DatabaseId = 
@DatabaseId)
SET @DatabaseName = (SELECT DatabaseName FROM RestoreVerifyDatabases WHERE DatabaseId = 
@DatabaseId)

as:

    SELECT @Path = LastBackupFileName, @DatabaseName = DatabaseName FROM RestoreVerifyDatabases WHERE DatabaseId = @DatabaseId

You also have a RAISEERROR. I suspect that is because you do a count(*), rather than selecting actually existing @databaseids. This works in an ideal scenario, where databases never get deleted. In the reasl world, though, you'd go from databaseid 1 to 5, because 2, 3, and 4 were removed. Your count will still be 50 databases, but you'd miss all databases with ids above the count due to these gaps. You'd be trying to process the databaseid that no longer exists, and miss the ones with an id > 50.

You could instead write your loop to do something like the following:

SELECT @DatabaseID = MIN(DatabaseID) FROM dbo.RestoreVerifyDatabases
WHILE @datbaseID IS NOT NULL
BEGIN
    -- Do stuff

    SELECT @DatabaseID = MIN(DatabaseID) FROM dbo.RestoreVerifyDatabases WHERE databaseID > @databaseID
END

Finally, your dynamic code isn't working. You are adding literal text rather than the value of the parameters. If I print the value of @Update at the end, it shows as:

UPDATE RestoreVerifyDatabases
        SET Confirmed = @DB_Text   @DatabaseName
        WHERE DatabaseID = @DatabaseId

Your code should be something like:

SET @Update= CONCAT('UPDATE RestoreVerifyDatabases SET Confirmed = ''', @DB_Text, ' ',  @DatabaseName, ''' WHERE DatabaseID = ',  @DatabaseId)

Which outputs:

UPDATE RestoreVerifyDatabases SET Confirmed = 'Backup has been confirmed for Last' WHERE DatabaseID = 2
  • Related