0

We have a database that we technically have admin access to on a database server. I can access the server and database on SSMS just fine, but can't actually RDP into that server as its controlled by the DBA team, which is expected.

I'm tasked to optimize the database, as currently we have a ridiculous amount of views that are just pivot and unpivot images of tables we implemented as part of a POC design last summer.

Since we are satisfied with the POC phase, I'm trying to reduce these views and so before I do that I need to export the data to csv file.

I am using the following command (based on this suggestion) in SSMS to do so:

EXEC xp_cmdshell 'bcp "select * from view1" queryout "\\fin-nas.dev.domain.com\abc01\CSV_Files\file1.csv" -c -t, -U "user123" -P "Password123" -S "dbserver.dev.domain.com" -d "Database1"';

I am running into the following issue:

SQLState = S1000, NativeError = 0
Error = [Microsoft][ODBC Driver 13 for SQL Server]Unable to open BCP host data-file

After some research, I realized that either:

  • file1.csv has to be created first in the directory specified (\\fin-nas.dev.domain.com\abc01\CSV_Files) which I did create

  • or this is basically an access issue, so from this suggestion here, I ran

      xp_cmdshell 'whoami'; 
    

    and that returned what seems to be the account associated with the DBA login...

      domain\dom_sasql$
    

Does this mean I'm completely unable to export the data and only the DBA can do so?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Cataster
  • 3,081
  • 5
  • 32
  • 79
  • 3
    Have you tried running bcp on your local computer connecting to the SQL server over the network? – AlwaysLearning Jan 08 '21 at 05:55
  • 3
    You're trying to push from the SQL Server to an external folder. Just connect from your client machine using BCP and pull the data locally. – Nick.Mc Jan 08 '21 at 06:06
  • 1
    @AlwaysLearning yo, that actually worked!!! why was i overcomplicating it LOL – Cataster Jan 08 '21 at 06:06
  • Also if this is for the purposes of importing back into SQL Server, I suggest using native format, not CSV – Nick.Mc Jan 08 '21 at 06:07
  • @Nick.McDermaid native format? I do plan to import back into sql, i use a separate script for that – Cataster Jan 08 '21 at 06:08
  • Why don't you google "BCP native format" and see what I mean. You wont suffer from any quoting or escaped delimiter or data type issues. and you can use a very similar bcp command line to import it back in. – Nick.Mc Jan 08 '21 at 06:13
  • @Nick.McDermaid ohhh i see. i think we tried using bcp to import, but it didnt work due to some limitations we faced. I dont recall them as its been over 6 months, but i think it had to do with the fact that we had some of the columns as REAL datatype, and thats was causing some sorta error...so to overcome that issue, i ended up using sqlbulkcopy – Cataster Jan 08 '21 at 06:21

2 Answers2

0

Normally what you do is map a network drive, after that it's the same as normal. The bellow script does such a task by exporting all data associated with a given file-group you can change the query to export a single statement but this script was used for regular export and import between domains that did not trust each other where an FTP service was transporting the data between domains.

We could not do all data as it were "golden" records that only where allowed to be exported

/*******************************************************************
this script will generate thebcp out commands for all data from the 
users current connected database. The this script will only work if
both databases have the same ddl version, meaning same tables, same
columns same data definitions.
*******************************************************************/




SET NOCOUNT ON 
GO 
DECLARE  @Path                  nvarchar(2000)  = 'f:\export\'  -- storage location for bcp dump (needs to have lots of space!)
       , @Batchsize             nvarchar(40)    = '1000000'     -- COMMIT EVERY n RECORDS 
       , @Xmlformat             bit             = 0             -- 1 for yes to xml format, 0 for not xml
       , @SourceServerinstance  nvarchar(200)   = 'localhost'-- SQL Server \ Instance name 
       , @Security              nvarchar(800)   = ' -T '        -- options are -T (trusted), -Uloginid -Ploginpassword  
       , @GenerateDump          bit             = 0             -- 0 for storing data to disk, not 1 for loading from disk
       , @FileGroup             sysname         = 'Data';       -- Table filegroup that we are intrested in

--> set output to text and execute the query, then copy the generated commands, validate and execucte them                   
--------------------------------Do not edit below this line-----------------------------------------------------------------
DECLARE @filter TABLE(TABLE_NAME sysname)  
INSERT INTO @filter (TABLE_NAME)
SELECT o.name
  FROM sys.indexes as i 
  JOIN sys.objects as o on o.object_id = i.object_id
 WHERE i.data_space_id = FILEGROUP_ID(@FileGroup) 
   AND i.type_desc ='CLUSTERED'   
   and o.name not like 'sys%'   
 order by 1      

if(@GenerateDump=0)
begin

    --BCP-OUT TABLES 
    SELECT  'bcp "' + QUOTENAME( TABLE_CATALOG ) + '.' + QUOTENAME( TABLE_SCHEMA ) 
    + '.' + QUOTENAME( TABLE_NAME ) + '" out "' + @path + '' + TABLE_NAME + '.dat" -q -b"' 
    + @batchsize + '" -e"' + @path + 'Error_' + TABLE_NAME + '.err" -n -CRAW -o"' + @path + '' 
    + TABLE_NAME + '.out"  -S"' + @SourceServerinstance + '" ' + @security + '' 
    FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM @filter)

    if(@Xmlformat=0)
        begin
            print 'REM CREATE NON-XML FORMAT FILE '
            SELECT  'bcp "' + QUOTENAME( TABLE_CATALOG ) + '.' + QUOTENAME( TABLE_SCHEMA ) + '.'+ 
             QUOTENAME( TABLE_NAME ) + '" format nul -n -CRAW -f "' + @path + '' 
            + TABLE_NAME + '.fmt"  -S"' + @SourceServerinstance + '" ' + @security + '' 
            FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'  AND TABLE_NAME IN (SELECT TABLE_NAME FROM @filter)
        end
    else
        begin
            PRINT 'REM XML FORMAT FILE' 
            SELECT  'bcp "' +QUOTENAME( TABLE_CATALOG ) + '.' + QUOTENAME( TABLE_SCHEMA ) 
            + '.' + QUOTENAME( TABLE_NAME ) + '" format nul -x -n -CRAW -f "' 
            + @path + '' + TABLE_NAME + '.xml"  -S"' + @SourceServerinstance + '" ' + @security + '' 
            FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'  AND TABLE_NAME IN (SELECT TABLE_NAME FROM @filter) 
        end
end
else
begin
    print '--Make sure you backup your database first'
    --GENERATE CONSTRAINT NO CHECK 
    PRINT '--NO CHECK CONSTRAINTS' 
    SELECT 'ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME( TABLE_NAME ) + ' NOCHECK CONSTRAINT ' +  QUOTENAME( CONSTRAINT_NAME ) 
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME IN (SELECT TABLE_NAME FROM @filter)

    PRINT '--DISABLE TRIGGERS' 
    SELECT 'ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME( TABLE_NAME ) + ' DISABLE TRIGGER ALL' 
    FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM @filter)
    --TRUNCATE TABLE 
    SELECT 'TRUNCATE TABLE ' +QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME( TABLE_NAME ) + ' 
    GO ' 
    FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM @filter)

    --BULK INSERT 
    SELECT DISTINCT 'BULK INSERT ' + QUOTENAME(TABLE_CATALOG) + '.' 
    + QUOTENAME( TABLE_SCHEMA ) + '.' + QUOTENAME( TABLE_NAME ) + ' 
    FROM ''' + @path + '' + TABLE_NAME + '.Dat'' 
    WITH (FORMATFILE = ''' + @path + '' + TABLE_NAME + '.FMT'', 
    BATCHSIZE = ' + @batchsize + ', 
    ERRORFILE = ''' + @path + 'BI_' + TABLE_NAME + '.ERR'',         
    TABLOCK); 
    GO ' 
    FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM @filter)
    
    --GENERATE CONSTRAINT CHECK CONSTRAINT TO VERIFY DATA AFTER LOAD 
    PRINT '--CHECK CONSTRAINT' 


    SELECT 'ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME( TABLE_NAME ) + ' CHECK CONSTRAINT ' 
    FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM @filter)

    SELECT 'ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA)+'.'+ QUOTENAME( TABLE_NAME ) + ' ENABLE TRIGGER ALL' 
    FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM @filter)

    end
Walter Verhoeven
  • 3,867
  • 27
  • 36
  • interesting, although im honestly confused with this script. what is all this doing? also i ran the bcp command locally and it worked per @AlwaysLearning suggestion – Cataster Jan 08 '21 at 06:09
  • it generates the export statement that you can execute to use BCP the data out based on all data in a given filegroup name – Walter Verhoeven Jan 08 '21 at 10:43
0

Running bcp on local computer connecting to the SQL server over the network works if you dont have access. This is because xp_cmdshell is trying to push from the SQL Server to an external folder. Just connect from your client machine using BCP and pull the data locally.

  • Open CMD and run the bcp command.

Example (with spaced out columns):

bcp "select * from (select 'Style Code' as [Style Code], 'MY Code' as [MY Code] union select [Style Code], [MY Code] from UnPivoted_Table) q order by case [Style Code] when 'Style Code' then 0 ELSE 1 END" queryout "\\server.domain.com\CSV_Files\file1.csv" -c -t, -T -S "server1.db.com" -d "DB1"
Cataster
  • 3,081
  • 5
  • 32
  • 79