• Here's another options that differs from Jeff's good suggestion...

    It's a bit more convoluted than Jeff's suggestion but I offer it up because, in a situation like this, you probably don't want any indexes on the load/stage table... and... you probably DO want indexes on the read copy of the table. If that's not the case, go with Jeff's solution.

    This solution involves a wee bit of trickery know as partition switching. The following is an example...

    USE RDatabaseName;
    GO

    /* =================================================================================================
    Using the partition switch method...
    ================================================================================================= */
    IF OBJECT_ID('dbo.Client', 'U') IS NOT NULL
    DROP TABLE dbo.Client;
    GO
    CREATE TABLE dbo.Client (
        ClientID INT NOT NULL IDENTITY(1,1),
        ClientName VARCHAR(30) NOT NULL,
        CONSTRAINT pk_Client PRIMARY KEY CLUSTERED(ClientID)
            WITH(FILLFACTOR = 100)
        );
    GO

    IF OBJECT_ID('dbo.Client_Stage', 'U') IS NOT NULL
    DROP TABLE dbo.Client_Stage;
    GO
    CREATE TABLE dbo.Client_Stage (
        ClientID INT NOT NULL IDENTITY(1,1),
        ClientName VARCHAR(30) NOT NULL
        -- this will be a "load only" table, so we don't want any indexes
        );
    GO

    /* ================================================================================================
    Here's how it works...
        - The Client_Stage table gets loaded from whatever sources it gets loaded from.
        - Just before doing the switch, add any Client indexes to Client_Stage. (the partition switch requires the two tables both have the exact same indexes).
            (this will be the only portion of the procedure that will take time or be verbosly logged).
        - In a single transaction, truncate dbo.Client and switch from dbo.Client_Stage to dbo.Client and drop any indexes that were added to dbo.Client_Stage
            so that's ready to take in new data.

    Note: the partition switch itself is mearly a metadata change, so the whole thing takes less than a millisecond and
        dbo.Client is never offline or unavailable.
    ================================================================================================= */

    -- start by adding some data to the dbo.Client_Stage table...
    INSERT dbo.Client_Stage (ClientName)
    SELECT TOP (1000000)
        LEFT(ao1.name + ao2.name, 20)
    FROM
        sys.all_objects ao1
        CROSS JOIN sys.all_objects ao2;

    -- just a quick sanity check to verify that 1,000,000 rows have been added...
    SELECT COUNT(1) FROM dbo.Client_Stage;

    -- add a pk to dbo.Client_PreSwitch so that it matches dbo.Client...
    ALTER TABLE dbo.Client_Stage
        ADD CONSTRAINT pk_ClientStage
        PRIMARY KEY CLUSTERED(ClientID)
        WITH(FILLFACTOR = 100);

    BEGIN TRY
        BEGIN TRANSACTION
            TRUNCATE TABLE dbo.Client; --<< we're assuming that dbo.Client already has data in it.
            ALTER TABLE dbo.Client_Stage SWITCH TO dbo.Client;
            ALTER TABLE dbo.Client_Stage DROP CONSTRAINT pk_ClientStage;
        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
        IF @@trancount > 0 ROLLBACK TRANSACTION;
        DECLARE @msg nvarchar(2048) = error_message();
        RAISERROR (@msg, 16, 1);
    END CATCH;

    SELECT COUNT(1) FROM dbo.Client;
    SELECT COUNT(1) FROM dbo.Client_Stage;

    Note: the above assumes that you want dbo.Client_Stage to be a clean slate after each switch. If that's not the case and subsequent loads are appended to the existing data, that can be accomplished with a fairly minor change.
    USE DatabaseName;
    GO

    /* =================================================================================================
    Using the partition switch method...
    ================================================================================================= */
    IF OBJECT_ID('dbo.Client', 'U') IS NOT NULL
    DROP TABLE dbo.Client;
    GO
    CREATE TABLE dbo.Client (
        ClientID INT NOT NULL IDENTITY(1,1),
        ClientName VARCHAR(30) NOT NULL,
        CONSTRAINT pk_Client PRIMARY KEY CLUSTERED(ClientID)
            WITH(FILLFACTOR = 100)
        );
    GO

    IF OBJECT_ID('dbo.Client_Stage', 'U') IS NOT NULL
    DROP TABLE dbo.Client_Stage;
    GO
    CREATE TABLE dbo.Client_Stage (
        ClientID INT NOT NULL IDENTITY(1,1),
        ClientName VARCHAR(30) NOT NULL
        -- this will be a "load only" table, so we don't want any indexes
        );
    GO

    /* ================================================================================================
    Here's how it works...
        - The Client_Stage table gets loaded from whatever sources it gets loaded from.
        - Use SELECT INTO syntax to create a Client_PreSwitch table that will act as an intermediary
            between Client_Stage and Client.
        - Add any Client indexes to Client_PreSwitch. (the partition switch requires the two tables both have the exact same indexes).
        - In a single transaction, truncate dbo.Client and switch from dbo.Client_PreSwitch to dbo.Client and drop dbo.Client_PreSwitch.

    Note: the partition switch itself is mearly a metadata change, so the whole thing takes less than a millisecond and
        dbo.Client is never offline or unavailable.
    ================================================================================================= */

    -- start by adding some data to the dbo.Client_Stage table...
    INSERT dbo.Client_Stage (ClientName)
    SELECT TOP (1000000)
        LEFT(ao1.name + ao2.name, 20)
    FROM
        sys.all_objects ao1
        CROSS JOIN sys.all_objects ao2;

    -- just a quick sanity check to verify that 1,000,000 rows have been added...
    SELECT COUNT(1) FROM dbo.Client_Stage;

    SELECT
        cs.ClientID,
        cs.ClientName
        INTO dbo.Client_PreSwitch
    FROM
        dbo.Client_Stage cs;

    -- add a pk to dbo.Client_PreSwitch so that it matches dbo.Client...
    ALTER TABLE dbo.Client_PreSwitch
        ADD CONSTRAINT pk_ClientPreSwitch
        PRIMARY KEY CLUSTERED(ClientID)
        WITH(FILLFACTOR = 100);

    BEGIN TRY
        BEGIN TRANSACTION
            TRUNCATE TABLE dbo.Client; --<< we're assuming that dbo.Client already has data in it.
            ALTER TABLE dbo.Client_PreSwitch SWITCH TO dbo.Client;
            DROP TABLE dbo.Client_PreSwitch;
        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
        IF @@trancount > 0 ROLLBACK TRANSACTION;
        DECLARE @msg nvarchar(2048) = error_message();
        RAISERROR (@msg, 16, 1);
    END CATCH;

    SELECT COUNT(1) FROM dbo.Client;
    SELECT COUNT(1) FROM dbo.Client_Stage;

    Even if the first assumption was correct and you do want staging to be a clean slate after each switch, you could also use a variation on this theme (using the "preswitch" table) if you aren't able (or simply don't want to) add indexes to the staging table.
    you'd just want to truncate the staging table in an explicit transaction with the SELECT INTO preswitch.

    HTH,
    Jason