MS SQL data export/import

User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Cпасибо Тенгиз, сколько сразу новых (для меня!) идей!

tengiz wrote:Если Вам нужно импортировать данные в таблицу с другой структурой - используйте форматные файлы

В смысле форматировать файл в том же perl-е и потом импортировать или тут имеется в виду что-то еще?

tengiz wrote:или делайте импорт во view, содержащий только старые колонки. А также можно сделать bcp in во временную таблицу со стабильной структурой и уже оттуда вставлять в окончательную таблицу с новой структурой.


Это получается все равно что создать для каждого клиента по новой базе и перегонять из старой в новую.

tengiz wrote:Данных, кстати, много? А то если не очень много (тысячи строк), то и мета-скрипт можно было бы написать, который нарисует из реальной таблицы другой скрипт с кучей insert into...values... который загрузит собственно данные.


Очень мало пока данных, все на trial. Так балуются. Но в реальной рабочей версии будет много. А вы не могли бы привести какой-нибудь пример подобного скрипта, я бы дальше сама.

Еше раз преогромное спасибо,
Сабина
Niky
Уже с Приветом
Posts: 550
Joined: 31 Mar 2000 10:01
Location: Moscow --> Baltimore, MD

Post by Niky »

Что-то я совсем перестал понимать, чего хочется сделать. Если задача в том, чтобы добавить колонки к таблицам без потери данных, так они и так не потеряются - ALTER TABLE и все дела :pain1:
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Niky wrote:Что-то я совсем перестал понимать, чего хочется сделать. Если задача в том, чтобы добавить колонки к таблицам без потери данных, так они и так не потеряются - ALTER TABLE и все дела :pain1:


Так по сю пору и делали.
Но тогда надо каждый раз писать скрипт с alter table, копаясь при этом в том, кто что поменял и где.
Хотят чтобы данные слить, структуру пересоздать(db_schema, триггеры, views, lookup-ы то всегда up to date) и потом снова данные залить. И чтобы все одним скриптом делалось для каждого клиента.

Сабина
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Sabina wrote:
tengiz wrote:Если Вам нужно импортировать данные в таблицу с другой структурой - используйте форматные файлы

В смысле форматировать файл в том же perl-е и потом импортировать или тут имеется в виду что-то еще?


Ага, нашла http://www.schemamania.org/jkl/booksonline/SQLBOL70/html/impt_bcp_16.htm

Сабина
Niky
Уже с Приветом
Posts: 550
Joined: 31 Mar 2000 10:01
Location: Moscow --> Baltimore, MD

Post by Niky »

Ну есть и посвежее: MS SQL Server 2000 BOL.
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Niky wrote:Ну есть и посвежее: MS SQL Server 2000 BOL.


Да-да (печально так)
Только это все никак не проще чем те скрипты с DTS, что я написала. Format file создавать в interactive mode при каждом экспорте? 8O
И с DTS параметрами тоже ничего не вышло, там можно задавать параметры для queries или global variables, типа %client_path for data, %package_path и т.д. А имя базы параметром никак не передашь. :pain1:

Короче пусть берут вариант с DTS как есть. Я умываю руки.

Сабина
User avatar
tengiz
Уже с Приветом
Posts: 4468
Joined: 21 Sep 2000 09:01
Location: Sammamish, WA

Post by tengiz »

Sabina wrote:Очень мало пока данных, все на trial. Так балуются. Но в реальной рабочей версии будет много. А вы не могли бы привести какой-нибудь пример подобного скрипта, я бы дальше сама.

Например, прогон такого скрипта в pubs

Code: Select all

select 
'insert into discounts(discounttype,stor_id,lowqty,highqty,discount)values(' +
 isnull ('''' + discounttype  + '''', 'NULL') + ',' +
 isnull ('''' + stor_id       + '''', 'NULL') + ',' +
 isnull (ltrim (str (lowqty))       , 'NULL') + ',' +
 isnull (ltrim (str (highqty))      , 'NULL') + ',' +
 isnull (ltrim (str (discount))     , 'NULL') + ')'
from discounts

Выдаст вот это:

Code: Select all

insert into discounts(discounttype,stor_id,lowqty,highqty,discount)values('Initial Customer',NULL,NULL,NULL,11)
insert into discounts(discounttype,stor_id,lowqty,highqty,discount)values('Volume Discount',NULL,100,1000,7)
insert into discounts(discounttype,stor_id,lowqty,highqty,discount)values('Customer Discount','8042',NULL,NULL,5)

Прогон этого результата в результате вставит данные.

Понятно, что создание скрипта, создающего скрипт с insert можно полностью автоматизировать. Но это более-менее удовлетворительно работает с не очень большими объёмами данных. Bulk load в любом случае и удобнее и быстрее.

Для создания форматных файлов отнюдь не нужна интерактивная сессия. У bcp.exe есть опция formatonly, которая в пакетном режиме создаст форматный файл.

------------------

Пояснение к варианту с временными view.

1. Перед сохранением данных, создаётся view для каждой таблицы, данные из которой нужно сохранить. Причём во view нужно явно перечислить все колонки, select * не годится. Скрипт для создания view сохраняется.

2. Делается bcp out не из таблиц, а из view, причем

3. После пересоздания схемы со всеми изменениями в базе снова создаются эти view ровно так как они были созданы в предыдущей версии базы. Поэтому даже если в таблицах добавились колонки или колонки поменяли свои относительные позиции, bcp in в эти view отработает правильно. Если изменения существующих колонок могут затронуть свойство NULL/NOT NULL, то native режим bcp применять нельзя. Только char/widechar.

4. Дропнуть временные view.

Я так понимаю, что это должно решить все Ваши проблемы.

------------------

Похожую технику с view можно применять и для DTS. Чтобы не мучаться с именем базы данных, создайте view для каждой таблицы Вашей базы, но только не в самой базе, а в tempdb. view в tempdb, разумеется, должны смотреть в таблицы настоящей базы. После чего пишется DTS пакет, который всегда работает только с tempdb, но по факту читает и пишет в нужную Вам базу.
Cheers
User avatar
Dmitry67
Уже с Приветом
Posts: 28294
Joined: 29 Aug 2000 09:01
Location: SPB --> Gloucester, MA, US --> SPB --> Paris

Post by Dmitry67 »

Dmitry67 wrote:Сабина

PS. Не по теме, Дима а вы в какой части Парижа живете/работаете?
Я работала под Парижем в Massy, было довольно-таки тоскливо cмотреть на южный пригород после толкания в RER каждое утро. А вот знакомый работал в La Defense, говорит, совсем другое восприятие жизни 8)
А во Finac ходите по выходным ? :)


А Massy-Palaiseau (ligne B) ? Помню, помню старика Крупского :)
Я сейчас живу в Montrouge (RER LaPlace, проезжали ее) но я езжу от Porte d'Orleans. На работу езжу на Trocadero по 6 ветке. Я люблю большие города, городскую толчею... Пригороды не люблю особенно после US
А Вы где сейчас ?

Во fnac не хожу. ПРодукты покупаю во FRANPRIX. А шопаться не люблю :)
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
User avatar
chepackav
Уже с Приветом
Posts: 1513
Joined: 03 Apr 2001 09:01
Location: London, UK

Post by chepackav »

Sabina wrote:
Niky wrote:Что-то я совсем перестал понимать, чего хочется сделать. Если задача в том, чтобы добавить колонки к таблицам без потери данных, так они и так не потеряются - ALTER TABLE и все дела :pain1:


Так по сю пору и делали.
Но тогда надо каждый раз писать скрипт с alter table, копаясь при этом в том, кто что поменял и где.
Хотят чтобы данные слить, структуру пересоздать(db_schema, триггеры, views, lookup-ы то всегда up to date) и потом снова данные залить. И чтобы все одним скриптом делалось для каждого клиента.

Сабина



Посмотрите здесь : Red Gate - стоит копейки и работает оченнь хорошо.[/url]
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

chepackav wrote:Посмотрите здесь : Red Gate - стоит копейки и работает оченнь хорошо.[/url]


Cпасибо, мне Илья уже подсказал про этот тул. К сожалению начальство и на эти копейки раскошелится сейчас не может :(

Сабина
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Dmitry67 wrote:А Massy-Palaiseau (ligne B) ? Помню, помню старика Крупского :)


Есть такая контора CGG, там контрольный пакет принадлежит Эльфу и Тоталю, они основали эту контору для своих геофизических нужд. Я на них в России работала, но иногда и в Европе по нескольку месяцев доводилось выбираться.

Dmitry67 wrote:Я сейчас живу в Montrouge (RER LaPlace, проезжали ее) но я езжу от Porte d'Orleans. На работу езжу на Trocadero по 6 ветке. Я люблю большие города, городскую толчею... Пригороды не люблю особенно после US


Ну тогда вам бы тоже в Масси не понравилось :)
Я люблю городскую толчею и Париж весь обошла пешком раз "дцать". Но это когда еще была "холостая, незамужняя" :)

Сейчас я живу в часе езды от SF и San Jose, то есть почти что в Силиконовой Долине. Мне безумно нравится такое сочетание красивой природы, хай тека и городской толчеи (SF рядом, если уж так приспичило).
У нас рядом красивейшие холмы, в которых часто застревают облака и погода при переезде через холмы резко меняется. Когда я езжу на работу каждый день этот вид залитых солнцем холмов с ветряными мельницами создает такое неповторимое настроение... Одним словом я не хочу никуда отсюда уезжать, хотя паспорт уже есть и можно хоть в Париж, хоть еще куда.
Путешествовать, это другое дело, но пока фокус на зарабатывании денег :roll: Хочется перебраться в дом тех же размеров, что наш теперяшний, но поближе к цивилизации, детям на колледж, на те же путешествия...

Dmitry67 wrote:Во fnac не хожу. ПРодукты покупаю во FRANPRIX. А шопаться не люблю :)


А я там постоянно тусовалась. Впрочем я шопать очень даже люблю под настроение. :mrgreen:

Сабина
User avatar
BlueMoon
Уже с Приветом
Posts: 292
Joined: 18 Jun 2003 16:05

Post by BlueMoon »

del
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

del
Last edited by Sabina on 04 Dec 2003 23:46, edited 1 time in total.
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Домучала птичку наконец-то :D
Получился вот такой скрипт, который делает экспорт данных изо всех баз на сервере (кроме всяких tempdb и проч.) и создает format files.

Замечания и критика принимаются с энтузиазмом:

-------------------------------------------------------------------------
IF OBJECT_ID('dbo.up_expAlltables') IS NOT NULL
DROP PROCEDURE dbo.up_expAllTables
GO

CREATE PROCEDURE dbo.up_expAllTables
AS

SET NOCOUNT ON

--Declare variables
DECLARE @strDBName SYSNAME --holds database names
DECLARE @lngDBCount INTEGER --holds database count
DECLARE @lngCounter1 INTEGER --loop counter
DECLARE @strTableName SYSNAME --holds table names
DECLARE @lngTabCount INTEGER --holds table count
DECLARE @lngCounter2 INTEGER --loop counter
DECLARE @strSQL NVARCHAR(4000) --dynamic sql string
DECLARE @myQuery NVARCHAR(1000) --bcp query for format files and export
DECLARE @myServer NVARCHAR(100) --server name
DECLARE @myOutPath NVARCHAR(200) --path for exported data files
DECLARE @myFormatPath NVARCHAR(200) --path for format files
DECLARE @myLogin NVARCHAR(50) --login name
DECLARE @myPassword NVARCHAR(50) --password

SET @myServer = (SELECT @@SERVERNAME)
SET @myLogin = [type your username here in quotes]
SET @myPassword = [type your passowrd here in quotes]
--Create temp tables to hold database and table names
CREATE TABLE #tDBName
(
numID INTEGER IDENTITY(1,1)
,strDBName SYSNAME
)

CREATE TABLE #tTableName
(
numID INTEGER IDENTITY(1,1)
,strTableName SYSNAME
)

--Populate database names
INSERT INTO #tDBName (strDBName)
SELECT name from master.dbo.sysdatabases
WHERE name NOT IN ('master','model','msdb','Northwind','pub','tempdb')
SET @lngDBCount = @@ROWCOUNT --How many databases
SET @lngCounter1 = @lngDBCount --Preserves original count for future use

--Loop through database names
WHILE @lngCounter1 <> 0
BEGIN
--Populate database name variable
SET @strDBName = (SELECT strDBName FROM #tDBName WHERE numID = @lngCounter1)

--Populate table names
SET @strSQL = 'INSERT INTO #tTableName (strTableName)
SELECT name FROM ' + @strDBName + '.dbo.sysobjects WHERE xtype = ''u''' --only use user tables
EXEC sp_executesql @strSQL

SET @lngTabCount = (SELECT @@ROWCOUNT) --how many tables in this database
SET @lngCounter2 = @lngTabCount --Preserve table number for future use

--Header
SELECT @strDBName + ' Database'

--Loop through all tables
WHILE @lngCounter2 <> 0
BEGIN
--Populate table name variable
SET @strTableName = (SELECT strTableName FROM #tTableName WHERE numID = @lngCounter2)

-- Core part with creating format files and export files-----
SET @myOutPath = 'C:\SQL\ExportData\' + @strDBName + '_' + @strTableName + '.txt'
SET @myFormatPath = 'C:\SQL\ExportData\' + @strDBName + '_' + @strTableName + '.fmt'
--creating format file
SET @myQuery = N'execute master.dbo.xp_cmdshell ''bcp "' + LTRIM(RTRIM(@strDBName)) +
'..' + LTRIM(RTRIM(@strTableName)) + '" format "' + LTRIM(RTRIM(@myOutPath)) +
'" -S"' + LTRIM(RTRIM(@myServer)) + '" -U"' + LTRIM(RTRIM(@myLogin)) + '" -P"' +
LTRIM(RTRIM(@myPassword)) + '" -f"' + LTRIM(RTRIM(@myFormatPath)) + '" -c'''
execute (@myQuery)
--exporting data
SET @myQuery = N'execute master.dbo.xp_cmdshell ''bcp "' + LTRIM(RTRIM(@strDBName)) +
'..' + LTRIM(RTRIM(@strTableName)) + '" out "' + LTRIM(RTRIM(@myOutPath)) +
'" -S"' + LTRIM(RTRIM(@myServer)) + '" -U"' + LTRIM(RTRIM(@myLogin)) +
'" -P"' + LTRIM(RTRIM(@myPassword)) + '" -c -E'''
execute (@myQuery)
-- core part ends--

--Move backward through tables
SET @lngCounter2 = @lngCounter2 - 1
END

--Move backward through databases
SET @lngCounter1 = @lngCounter1 - 1

--Clean out table name temp table
TRUNCATE TABLE #tTableName
END

DROP TABLE #tDBName
DROP TABLE #tTableName
GO

--Test
EXEC dbo.up_expAllTables

------------------------------------------------------------------

Тенгиз, а вас я просто не знаю как благодарить. Вы так мне все здорово "разжевали"

Сабина
User avatar
Dmitry67
Уже с Приветом
Posts: 28294
Joined: 29 Aug 2000 09:01
Location: SPB --> Gloucester, MA, US --> SPB --> Paris

Post by Dmitry67 »

Код я естественно не проверял
Пара мелких замечаний; делать truncate в конце и делать drop временным таблицам совсем даже не нужно (и в некоторых случаях даже вредно)
Кроме того таблицы-переменные работают быстрее временных таблиц, но для данного случая это несущественно
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Sabina wrote:Получился вот такой скрипт, который делает экспорт данных изо всех баз на сервере (кроме всяких tempdb и проч.) и создает format files.
-------------------------------------------------------------------------
IF OBJECT_ID('dbo.up_expAlltables') IS NOT NULL
DROP PROCEDURE dbo.up_expAllTables
GO


Теперь сижу ломаю голову как это все в batch file запихать...
Получается надо разбивать на кучку queries и потом их запускать через isql...
Тогда непонятно как например сделать @@ROWCOUNT, если создание временной таблицы и ее update вынесены в отдельный скрипт, а результат надо вернуть в основной скрипт?

Или есть еще какая утилита, которая может прямо user procedure из командной cтроки запускать?

Cабина
Niky
Уже с Приветом
Posts: 550
Joined: 31 Mar 2000 10:01
Location: Moscow --> Baltimore, MD

Post by Niky »

isql -q "EXEC dbo.up_expAllTables" не пробовали?
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Niky wrote:isql -q "EXEC dbo.up_expAllTables" не пробовали?


Спасибо, сейчас попробую. А нельзя ли вместе с опцией -q передать еще и параметры

Code: Select all

%server%,
%db%,
%user%,
%pwd%,
%path%



Сабина
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Sabina wrote:А нельзя ли вместе с опцией -q передать еще и параметры

Code: Select all

%server%,
%db%,
%user%,
%pwd%,
%path%

Сабина


Я все-таки подумываю о замене этой up на batch file из нескольких "isql" и "bcp"
Получается масло масляное - запускать up содержащую "execute master.dbo.xp_cmdshell"

Вопрос только в том как из query [QUERY_NAME]

Code: Select all

CREATE TABLE #tTableName
(
numID INTEGER IDENTITY(1,1)
,strTableName SYSNAME
)

        --Populate table names
   SET @strSQL = 'INSERT INTO #tTableName (strTableName)
   SELECT name FROM ' + @strDBName + '.dbo.sysobjects WHERE xtype = ''u''' --only use user tables
   EXEC sp_executesql @strSQL

   SET @lngTabCount = (SELECT @@ROWCOUNT) --how many tables in this database


вернуть ROWCOUNT в batch file?

Можно сделать:

Code: Select all

isql -q[QUERY_NAME] -oC:\FILE1.TXT


Но мне в файл не нужно, надо что-то вроде:

set cntTables = isql -q[QUERY_NAME] -o??????

Может тут можно с stdout что-нибудь придумать?

Сабина
Niky
Уже с Приветом
Posts: 550
Joined: 31 Mar 2000 10:01
Location: Moscow --> Baltimore, MD

Post by Niky »

isql -q "EXEC dbo.up_expAllTables" -U login -P password -S server -d database

Что за path - не понятно.
Если так уж хочется именно батч вместо процедуры, есть еще опция -i, позволяющая выполнить SQL statements, записанные в файл. Но зачем это нужно в вашем случае, понять не могу.
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Niky wrote:isql -q "EXEC dbo.up_expAllTables" -U login -P password -S server -d database
Что за path - не понятно.


Это path к папке C:\ExportDataFiles, который hard coded в том примере, что я привела выше.

Niky wrote:Если так уж хочется именно батч вместо процедуры, есть еще опция -i, позволяющая выполнить SQL statements, записанные в файл. Но зачем это нужно в вашем случае, понять не могу.


Мне просто казалось что запускать процедуру внутри которой запускается bcp через xp_cmdshell это как "масло масляное". Или я не права?

Спасибо вам большое за все ваши подсказки, мне они очень помогли.

Сабина
Niky
Уже с Приветом
Posts: 550
Joined: 31 Mar 2000 10:01
Location: Moscow --> Baltimore, MD

Post by Niky »

Этот path надо передавать в процедуру как параметр, вызов isql будет выглядеть так:

isql -q "EXEC dbo.up_expAllTables 'C:\ExportDataFiles'" ...
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Niky wrote:Этот path надо передавать в процедуру как параметр, вызов isql будет выглядеть так:

isql -q "EXEC dbo.up_expAllTables 'C:\ExportDataFiles'" ...


А как при этом EXEC поймет какой параметр я передаю как 'C:\ExportDataFiles' ?

И как isql посадит юзернейм, пароль и проч. в нужные переменные?

Наверное нужно что-то мнеять в синатаксисе самой user procedure? Пока же там только

--Declare variables

Code: Select all

DECLARE @strDBName SYSNAME --holds database names
DECLARE @lngCounter INTEGER --loop counter
DECLARE @strTableName SYSNAME --holds table names
DECLARE @lngTabCount INTEGER --holds table count
DECLARE @strSQL NVARCHAR(4000) --dynamic sql string
DECLARE @myQuery NVARCHAR(1000) --bcp query for format files and export
DECLARE @myServer NVARCHAR(100) --server name
DECLARE @myOutPathFolder NVARCHAR(200) --path for exported data folder
DECLARE @myOutPath NVARCHAR(200) --full path for exported data files
DECLARE @myFormatPath NVARCHAR(200) --full path for format files
DECLARE @myLogin NVARCHAR(50) --login name
DECLARE @myPassword NVARCHAR(50) --password

SET @myServer = (SELECT @@SERVERNAME)
SET @myLogin = '.....'
SET @myPassword = '......'
SET @strDBName = '....._DEV'
SET @myOutPathFolder = 'C:\ExportDataFiles'



Сабина
Niky
Уже с Приветом
Posts: 550
Joined: 31 Mar 2000 10:01
Location: Moscow --> Baltimore, MD

Post by Niky »

Процедуру конечно надо менять, примерно так:

Code: Select all

CREATE PROCEDURE dbo.up_expAllTables 
@myOutPath NVARCHAR(200) ,
@myServer NVARCHAR(100) ,
@myLogin NVARCHAR(50) ,
@myPassword NVARCHAR(50) ,
@strDBName SYSNAME
AS
...

Параметры можно передать :
1. по порядку - тогда вызов процедуры будет выглядеть так:

Code: Select all

EXEC dbo.up_expAllTables 'C:\tmp' , 'mysql2000dev' , 'user1' , 'pass1' , 'pubs'

2. по именам - тогда вызов процедуры будет выглядеть так:

Code: Select all

EXEC dbo.up_expAllTables @myOutPath='C:\tmp' , 
@myServer='mysql2000dev' ,
@strDBName='pubs',
@myLogin='user1' , @myPassword='pass1'
User avatar
Sabina
Уже с Приветом
Posts: 5669
Joined: 13 Oct 2000 09:01
Location: East Bay, CA

Post by Sabina »

Niky wrote:Процедуру конечно надо менять, примерно так:
[code]
CREATE PROCEDURE dbo.up_expAllTables


Ну теперь вы мне все до конца по полочкам разложили. Спасибо огромное. Да-а-а, DBA бы из меня точно не получился :)

Сабина

Return to “Вопросы и новости IT”