SQL-使用变量访问数据库

时间:2019-06-05 10:31:01

标签: sql sql-server tsql

我正在尝试访问每个季度在新数据库中重新创建的表。表名保持不变,但是会创建一个新的数据库名。 我要实现的目标是使用select语句包含一个变量,该变量将查看范围为Q317至Q119的特定数据库。目前,我已经设置了选择代码,但是我不得不重用相同的代码,但是更改每个数据库的季度。我现在正在做一种更有效的方法吗?
为了使事情更棘手,“四分之一”值必须是字符串而不是整数。

如您所见,我不是专家,我尝试将变量传递给可以工作的字符串,但是我无法成功进行迭代。

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 个答案:

答案 0 :(得分:1)

那呢?

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

您可以使用动态SQL代替最后的PRINT语句:

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

最良好的祝愿
迈克尔

答案 1 :(得分:0)

您可以做的是在数据库中创建一个序列,请检查以下链接 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

答案 2 :(得分:0)

我建议您从sysdatabases开始创建SQL语句。

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)