Как зациклить запрос в разных базах данных в T-SQL? - PullRequest
0 голосов
/ 15 мая 2018

У меня следующий запрос, который нужно выполнить в разных базах данных, но имя таблицы и ее структура одинаковы.

--query to be executed
select cust_num, name, credit_hold, credit_hold_reason, 
   (case 
       when credit_hold_reason = 'NP' then 'No payments'
       when credit_hold_reason = 'UK' then 'Unknown'
       when credit_hold_reason = 'BK' then 'Bankruptcy'
    end) as 'Type of credit hold reason',
 credit_hold_date, credit_limit
from [database_01].[dbo].[custaddr] 
--- from [database_02].[dbo].[custaddr] 
--- from [database_03].[dbo].[custaddr] 
order by credit_hold_reason asc

Как видите, мне просто нужно изменить имя базы данных или«loop» в некоторой переменной , которая содержит имя базы данных, например,

tables_in_loop = ['[database_01].[dbo].[custaddr]', 'from [database_02].[dbo].[custaddr]', 'from [database_03].[dbo].[custaddr]']

Когда у вас есть имя базы данных, к ним создается соединение и всеэти базы данных находятся на одном сервере.

У меня нет подходов или кодов по этому поводу, потому что это требует более глубоких знаний в SQL, и, к сожалению, я пока не эксперт.Я прочитал следующий пост SQL Server: как получить имя базы данных в качестве параметра в хранимой процедуре , и подход к ее решению выглядит примерно так:

declare @dbname nvarchar(255);    
set @dbname = 'db1';    

if @dbname = 'db1'
    use db1;
else if @dbname = 'db2'
    use db2;

, но @dbnameнеобходимо увеличить до следующей базы данных, и это не указано в ссылке.

Буду признателен за любую помощь или код здесь.

Ответы [ 3 ]

0 голосов
/ 15 мая 2018

Мне нравится создавать временную таблицу для результатов запроса, создавать переменную таблицы для моего списка баз данных для запроса, а затем циклически проходить по этому списку баз данных для выполнения запроса для каждого, вставляя результаты в временную таблицу.

Таким образом, вы можете запросить результаты несколько раз после запуска всего цикла цикла только один раз.

Попробуйте это (вам нужно изменить объявление временной таблицы #results и предложение where первого оператора вставки):

--drop temp table if it exists; this clears the results each time you run the full script
if object_id('tempdb..#results') is not null
    drop table #results
go

--recreate temp table; this is used for storing the result set.  It's created as a temp table instead of a table variable so that it can be queried repeatedly after gathering results.
create table #results (
    dbName varchar(128)
    ,cust_num varchar(128)
    , [name] varchar(128)
    , credit_hold bit
    , credit_hold_reason varchar(128)
    , [Type of credit hold reason] varchar(128)
    , credit_hold_date varchar(128)
    , credit_limit int);  --adjust column declaration as needed for query results

--create a variable to track the database list
declare @dbList table (dbName varchar(128), indx int)

insert into @dbList
select dbName = name, row_number() over (order by name) 
from master.sys.databases
--where --insert your own where clause here to narrow down which databases to run the query on.

--declare variables for use in the while loop
declare @index int = 1
declare @totalDBs int = (select count(*) from @dbList)
declare @currentDB varchar(128)
declare @cmd varchar(300)
--define the command which will be used on each database.
declare @cmdTemplate varchar(300) = '
    use {dbName};
    insert into #results
    select db_name(), cust_num, name, credit_hold, credit_hold_reason, 
       (case 
           when credit_hold_reason = ''NP'' then ''No payments''
           when credit_hold_reason = ''UK'' then ''Unknown''
           when credit_hold_reason = ''BK'' then ''Bankruptcy''
        end) as ''Type of credit hold reason'',
     credit_hold_date, credit_limit
    from [custaddr] 
    order by credit_hold_reason asc
'

--loop through each database and execute the command
while @index <= @totalDBs 
begin
    set @currentDB = (select dbName from @dbList where indx = @index)
    set @cmd = replace(@cmdTemplate, '{dbName}', @currentDB)

    execute(@cmd)

    set @index += 1
end

--see the results of the command; this can be queried repeatedly by itself after it's created the first time
select *
from #results

Обратите внимание, что циклическое преобразование табличной переменной более эффективно, чем объявление курсора.

0 голосов
/ 15 мая 2018

Я спросил: «Другими словами, когда вы выполняете из [database_02]. [Dbo]. [Custaddr] будет ли ваше соединение подключено к database_02?»

Вы ответили:

когда я выполню [database_02]. [Dbo]. [Custaddr], тогда мой запрос будет запущен против database_02 и выполните [database_03]. [dbo]. [custaddr], затем мой запрос будет запущен к базе данных_03 - Alejandro BR

Итак, я понимаю, что это означает две вещи:

1) Вы будете подключены к базе данных, под которой вы выполняете запрос.
2) Вы хотите выполнить эти запросы отдельно. Другими словами, вы не пытаетесь объединить результаты в единый набор результатов для всех баз данных.

Другими словами, вы не выполняете кросс-запросы к базе данных. Я заметил, что вы не использовали термин «соединение» в своем ответе, поэтому я начинаю думать, что это концепция, которую вы упускаете.

Решение простое, используйте два имени части вместо 3 имен частей:

from [dbo].[custaddr] 

Это гарантирует, что при изменении соединения с другими базами данных запрос будет выполняться к этой базе данных.

В контексте приложения гораздо проще динамически создавать строку подключения или настраивать ее с помощью нескольких строк подключения в структуре данных.

Если вы начнете динамически создавать запросы для такого простого варианта использования, то вы слишком усложняете ситуацию. У динамических запросов есть ряд минусов, которые выходят за рамки этого вопроса, но по ним легко найти много информации.

0 голосов
/ 15 мая 2018

Я думаю, тебе просто нужен союз

select cust_num, name, credit_hold, credit_hold_reason, 
      (case 
          when credit_hold_reason = 'NP' then 'No payments'
          when credit_hold_reason = 'UK' then 'Unknown'
          when credit_hold_reason = 'BK' then 'Bankruptcy'
       end) as 'Type of credit hold reason',
     credit_hold_date, credit_limit
from [database_01].[dbo].[custaddr] 
union all
select cust_num, name, credit_hold, credit_hold_reason, 
      (case 
          when credit_hold_reason = 'NP' then 'No payments'
          when credit_hold_reason = 'UK' then 'Unknown'
          when credit_hold_reason = 'BK' then 'Bankruptcy'
       end) as 'Type of credit hold reason',
     credit_hold_date, credit_limit  
from [database_02].[dbo].[custaddr] 
union all
select cust_num, name, credit_hold, credit_hold_reason, 
      (case 
          when credit_hold_reason = 'NP' then 'No payments'
          when credit_hold_reason = 'UK' then 'Unknown'
          when credit_hold_reason = 'BK' then 'Bankruptcy'
       end) as 'Type of credit hold reason',
     credit_hold_date, credit_limit
from [database_03].[dbo].[custaddr]  
order by credit_hold_reason asc  

TLDR комментарии. Вы хотите что-то, кроме союза.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...