SQL - Доступ к базам данных с помощью переменной - PullRequest
1 голос
/ 05 июня 2019

Я пытаюсь получить доступ к таблице, которая воссоздается в новой базе данных каждый квартал. Имя таблицы остается прежним, но создается новое имя базы данных. Я пытаюсь добиться использования оператора select для включения переменной, которая будет смотреть на конкретную базу данных с диапазоном от Q317 до Q119. На данный момент у меня настроен код выбора, но я должен повторно использовать тот же код, но изменить квартал для каждой базы данных. Есть ли более эффективный способ сделать это, чем я сейчас занимаюсь?
Чтобы усложнить задачу, значение Quarter должно быть строкой, а не целым числом.

Как видите, я не эксперт, и я пытался передать переменные в строку, которая работает, но мне не удается успешно ее повторить.

declare @tablename varchar(50)
set @tablename = '2'
EXEC('SELECT DISTINCT [GAELTACHT] FROM [EDB_Q' + @tablename + '18].[dbo].[POSTAL_ADDRESS]')

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

SELECT 'Q119' AS Quarter,  Count(BUILDING_ID) FROM Towns.CITY_Q119
UNION ALL
SELECT 'Q418' AS Quarter,  Count(BUILDING_ID) FROM Towns.CITY_Q418
UNION ALL
SELECT 'Q318' AS Quarter,  Count(BUILDING_ID) FROM Towns.CITY_Q318 
UNION ALL
SELECT 'Q218' AS Quarter,  Count(BUILDING_ID) FROM Towns.CITY_Q218
UNION ALL
SELECT 'Q118' AS Quarter,  Count(BUILDING_ID) FROM Towns.CITY_Q118 
UNION ALL
SELECT 'Q417' AS Quarter,  Count(BUILDING_ID) FROM Towns.CITY_Q417

В идеале, я хотел бы иметь 1 оператор select, который каким-то образом итерирует (но использует строку на целых числах) от значений 218 до 119. Я не знаю, возможно ли то, что я запрашиваю?

Ответы [ 3 ]

1 голос
/ 05 июня 2019

Как насчет этого?

DECLARE @quarterStart int = 2
DECLARE @quarterEnd int = 1
DECLARE @yearStart int = 18
DECLARE @yearEnd int = 19

DECLARE @year int
DECLARE @quarter int

DECLARE @quarterForDbName nvarchar(4)
DECLARE @sqlStatement nvarchar(max)

SET @year = @yearStart
SET @quarter = @quarterStart
SET @sqlStatement = ''

WHILE @year <= @yearEnd
BEGIN
   WHILE ((@year < @yearEnd AND @quarter <= 4) OR (@year = @yearEnd AND @quarter <= @quarterEnd))
   BEGIN
      SET @quarterForDbName = 'Q' + CAST(@quarter AS nvarchar(1)) + CAST(@year AS nvarchar(2))
      SET @sqlStatement = @sqlStatement + 'SELECT ''' + @quarterForDbName + ''' AS Quarter, Count(BUILDING_ID) FROM Towns.CITY_' + @quarterForDbName + ' UNION ALL '
      SET @quarter = @quarter + 1
   END
   SET @quarter = 1
   SET @year = @year + 1
END

PRINT SUBSTRING(@sqlStatement, 1, LEN(@sqlStatement) - 10)

Результат:

SELECT 'Q218' AS Quarter, Count(BUILDING_ID) FROM Towns.CITY_Q218 UNION ALL SELECT 'Q318' AS Quarter, Count(BUILDING_ID) FROM Towns.CITY_Q318 UNION ALL SELECT 'Q418' AS Quarter, Count(BUILDING_ID) FROM Towns.CITY_Q418 UNION ALL SELECT 'Q119' AS Quarter, Count(BUILDING_ID) FROM Towns.CITY_Q119

Вместо оператора PRINT в конце вы можете использовать динамический SQL:

EXEC SUBSTRING(@sqlStatement, 1, LEN(@sqlStatement) - 10)

С наилучшими пожеланиями
Майкл

0 голосов
/ 05 июня 2019

Я бы посоветовал вам исключить создание оператора SQL из sysdatabases.

declare @sql varchar(max) = ''
select @sql += case when @sql = '' then '' else 'UNION ALL ' end + char(13) 
            + 'SELECT ''' + right(name, 4) + ''' AS Quarter, Count(Building_id) FROM ' + name + '.Towns.City_' + right(name, 4) + char(13)
  from sys.sysdatabases
 where name like 'EDB_Q%'

print @sql
exec(@sql)
0 голосов
/ 05 июня 2019

Что вы можете сделать, это создать последовательность в вашей базе данных, пожалуйста, проверьте ссылку ниже https://www.techonthenet.com/sql_server/sequences.php

CREATE SEQUENCE quarter_seq
  AS TINYINT
  START WITH 1
  INCREMENT BY -1
  MINVALUE 119
  MAXVALUE 218
  CYCLE
  CACHE 1;

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

Когда вы выбираете оператор select, используйте что-то вроде этого:

SELECT Current_Value 
FROM SYS.Sequences 
WHERE name='quarter_seq'

И брось его как строку.

Более подробную информацию о последовательностях и о том, как они работают, можно найти здесь:

https://docs.microsoft.com/en-us/sql/relational-databases/sequence-numbers/sequence-numbers?view=sql-server-2017

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