SQL-使用变量访问数据库

SQL-使用变量访问数据库,sql,sql-server,tsql,Sql,Sql Server,Tsql,我试图访问每季度在新数据库中重新创建的表。表名保持不变,但会创建一个新的数据库名。 我试图实现的是使用select语句包含一个变量,该变量将查看Q317到Q119范围内的特定数据库。目前,我已经设置了select代码,但我必须重用相同的代码,但要更改每个数据库的季度数。有没有比我现在做的更有效的方法 为了让事情变得更复杂,四分之一的值必须是字符串而不是整数 正如你所看到的,我不是专家,我尝试过将变量传递给字符串,但我无法成功地让它进行迭代 declare @tablename varchar(5

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

正如你所看到的,我不是专家,我尝试过将变量传递给字符串,但我无法成功地让它进行迭代

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

理想情况下,我会有一个select语句,它以某种方式在值218到119之间进行迭代(但在整数上使用字符串)。我不知道我的要求是否可行?

您可以在数据库中创建一个序列,请查看下面的链接

每次重新创建数据库时,都会增加该值。我猜你有一个脚本可以这样做,所以添加一行来增加序列

在执行select语句时,请使用以下内容:

SELECT Current_Value 
FROM SYS.Sequences 
WHERE name='quarter_seq'
然后把它当作一根绳子

有关序列及其工作方式的更多信息,请参见此处:

这个怎么样

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)
您可以使用动态SQL,而不是末尾的PRINT语句:

EXEC SUBSTRING(@sqlStatement, 1, LEN(@sqlStatement) - 10)
最美好的祝愿

Michael

我建议您将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)

理想情况下,你需要改变你的设计;这是你能做的吗?另一方面,在使用动态SQL时,不应注入原始字符串。始终参数化或正确引用(这是您在此处需要做的)您的值。您需要正确地形成动态sql,使用
SysName
而不是
VARCHAR(n)
并使用
QUOTENAME()
函数引用表名,注意不能将对象名作为参数传递。另外,我建议使用
sp\u execsql
而不是
EXEC
另外,您命名为
@TableName
的变量似乎不是表名,而是数据库名,因为您的表名是
[邮政地址]
。谢谢您的反馈,Sami。我完全愿意从头开始重建。Msg 11708,级别16,状态1,第1行为给定数据类型的参数“INCREMENT BY”指定了无效值。-请检查您的代码并在发布前进行测试。这里有人会否决你的答案…嗨,迈克尔,谢谢你的密码。我已经修改了我正在处理的真实数据,并得到了预期的结果
EXEC SUBSTRING(@sqlStatement, 1, LEN(@sqlStatement) - 10)
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)