有没有办法纯粹在 T-SQL 中从现有表生成创建脚本(即不使用 SMO,因为 T-SQL 无法访问 SMO)。假设一个存储过程接收一个表名并返回一个包含给定表的创建脚本的字符串?
现在让我描述一下我面临的情况,因为可能有不同的方法来解决这个问题。我有一个包含几十个数据库的实例。这些数据库都具有相同的架构、相同的表、索引等。它们是作为第三方软件安装的一部分创建的。我需要有一种与他们合作的方法,以便我可以以特别的方式从他们那里收集数据。dba.se 的好人已经在这里帮助了我如何在不同的数据库中创建触发器?
目前我需要找到一种方法来从所有数据库的表中进行选择。我已将所有数据库名称记录到一个名为的表中,Databasees并编写了以下脚本来对所有数据库执行 select 语句:
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
DROP TABLE #tmp
select * into #tmp from Database1.dbo.Table1 where 1=0
DECLARE @statement nvarchar(max) =
N'insert into #tmp select * from Table1 where Column1=0 and Cloumn2 =1'
DECLARE @LastDatabaseID INT
SET @LastDatabaseID = 0
DECLARE @DatabaseNameToHandle varchar(60)
DECLARE @DatabaseIDToHandle int
SELECT TOP 1 @DatabaseNameToHandle = Name,
@DatabaseIDToHandle = Database_Ref_No
FROM Databasees
WHERE Database_Ref_No > @LastDatabaseID
ORDER BY Database_Ref_No
WHILE @DatabaseIDToHandle …Run Code Online (Sandbox Code Playgroud) 免责声明:作为一个只使用数据库一小部分工作时间的人,请耐心等待。(大部分时间我在工作中进行 C++ 编程,但每个奇数月我都需要在 Oracle 数据库中搜索/修复/添加一些内容。)
我一再需要编写复杂的 SQL 查询,包括临时查询和内置于应用程序的查询,其中大部分查询只是重复“代码”。
用传统的编程语言编写这种可憎的东西会让你陷入困境,但我(我)还没有找到任何像样的技术来防止 SQL 查询代码重复。
编辑:第一,我要感谢对我的原始示例提供出色改进的回答者。但是,这个问题与我的示例无关。这是关于 SQL 查询中的重复性。因此,到目前为止的答案(JackP、Leigh)都很好地表明您可以通过编写更好的查询来减少重复性。然而,即便如此,您仍面临一些显然无法消除的重复性:这总是用 SQL 烦扰我。在“传统”编程语言中,我可以进行大量重构以最大程度地减少代码中的重复性,但是对于 SQL,似乎没有(?)工具可以实现这一点,除非开始编写重复性较低的语句。
请注意,我再次删除了 Oracle 标记,因为我真的很想知道是否没有允许更多内容的数据库或脚本语言。
这是我今天拼凑起来的一颗这样的宝石。它基本上报告了单个表的一组列中的差异。请浏览以下代码,尤其是。最后的大查询。下面我继续说。
--
-- Create Table to test queries
--
CREATE TABLE TEST_ATTRIBS (
id NUMBER PRIMARY KEY,
name VARCHAR2(300) UNIQUE,
attr1 VARCHAR2(2000),
attr2 VARCHAR2(2000),
attr3 INTEGER,
attr4 NUMBER,
attr5 VARCHAR2(2000)
);
--
-- insert some test data
--
insert into TEST_ATTRIBS values ( 1, 'Alfred', 'a', 'Foobar', …Run Code Online (Sandbox Code Playgroud) 给定两个带有名称和值的未定义行数的表,我将如何显示CROSS JOIN函数对其值的透视。
CREATE TEMP TABLE foo AS
SELECT x::text AS name, x::int
FROM generate_series(1,10) AS t(x);
CREATE TEMP TABLE bar AS
SELECT x::text AS name, x::int
FROM generate_series(1,5) AS t(x);
Run Code Online (Sandbox Code Playgroud)
例如,如果该函数是乘法,我将如何生成如下所示的(乘法)表,
所有这些(arg1,arg2,result)行都可以用
SELECT foo.name AS arg1, bar.name AS arg2, foo.x*bar.x AS result
FROM foo
CROSS JOIN bar;
Run Code Online (Sandbox Code Playgroud)
所以这只是一个演示问题,我希望这也适用于自定义名称——该名称不仅仅是CAST文本的参数,而是设置在表格中,
CREATE TEMP TABLE foo AS
SELECT chr(x+64) AS name, x::int
FROM generate_series(1,10) AS t(x);
CREATE TEMP TABLE bar AS
SELECT …Run Code Online (Sandbox Code Playgroud) 我做了以下存储过程:
ALTER PROCEDURE usp_actorBirthdays (@nameString nvarchar(100), @actorgender nvarchar(100))
AS
SELECT ActorDOB, ActorName FROM tblActor
WHERE ActorName LIKE '%' + @nameString + '%'
AND ActorGender = @actorgender
Run Code Online (Sandbox Code Playgroud)
现在,我尝试做这样的事情。也许我做错了,但我想确保这样的过程可以防止任何 SQL 注入:
EXEC usp_actorBirthdays 'Tom', 'Male; DROP TABLE tblActor'
Run Code Online (Sandbox Code Playgroud)
下图显示了在 SSMS 中执行的上述 SQL 并且结果显示正确而不是错误:
顺便说一句,我在查询完成后在分号后面添加了那部分。然后我再次执行它,但是当我检查表 tblActor 是否存在时,它仍然存在。难道我做错了什么?或者这真的是防注射的吗?我想我在这里也想问的是,这是一个像这样安全的存储过程吗?谢谢你。
sql-server-2008 security sql-server sql-injection dynamic-sql
我正在编写一个动态 sql 以在不同的数据库中删除和创建视图。
所以我写道:
set @CreateViewStatement =
'
USE ['+ @DB +'];
CREATE VIEW [dbo].[MyTable]
AS
SELECT ........something
exec (@CreateViewStatement)
Run Code Online (Sandbox Code Playgroud)
它给了我错误:
'CREATE VIEW' 必须是查询批处理中的第一条语句。
如果我删除 USE DATABASE 语句,它可以正常工作,但是不再指定数据库....
我怎么解决这个问题?
我听说它说您不想使用动态 SQL。你能给我一些具体的或现实生活中的例子吗?
就个人而言,我在我的数据库中多次使用它进行编码。我认为这是可以的,因为它的灵活性。
我的猜测是关于 SQL 注入或性能。还要别的吗?
我必须重构并记录一些foo.sql查询,这些查询将由一个数据库技术支持团队共享(用于客户配置等)。有些类型的票会定期出现,每个客户都有自己的服务器和数据库,但除此之外,架构是完全相同的。
存储过程目前不是一个选项。我正在争论是使用动态还是 SQLCMD,我没有使用过太多,因为我对 SQL Server 有点陌生。
SQLCMD 脚本我觉得对我来说绝对“看起来”更干净,更容易阅读并根据需要对查询进行小的更改,但也会强制用户启用 SQLCMD 模式。由于使用字符串操作编写查询而导致语法突出显示丢失,因此动态更加困难。
这些正在使用 Management Studio 2012,SQL 版本 2008R2 进行编辑和运行。这两种方法的优缺点是什么,或者一种方法或另一种方法的一些 SQL Server“最佳实践”是什么?其中一个比另一个“更安全”吗?
declare @ServerName varchar(50) = 'REDACTED';
declare @DatabaseName varchar(50) = 'REDACTED';
declare @OrderIdsSeparatedByCommas varchar(max) = '597336, 595764, 594594';
declare @sql_OrderCheckQuery varchar(max) = ('
use {@DatabaseName};
select
-- stuff
from
{@ServerName}.{@DatabaseName}.[dbo].[client_orders]
as "Order"
inner join {@ServerName}.{@DatabaseName}.[dbo].[vendor_client_orders]
as "VendOrder" on "Order".o_id = "VendOrder".vco_oid
where "VendOrder".vco_oid in ({@OrderIdsSeparatedByCommas});
');
set @sql_OrderCheckQuery = replace( @sql_OrderCheckQuery, '{@ServerName}', quotename(@ServerName) );
set @sql_OrderCheckQuery = …Run Code Online (Sandbox Code Playgroud) 我在尝试将 SSMS 的上下文动态更改为动态 SQL 中指定的数据库时遇到问题:
EXEC sys.sp_executesql N'USE db1 ' ;
Run Code Online (Sandbox Code Playgroud)
它成功执行,但 SSMS 的数据库上下文不会改变。
我试过对上面的稍作修改
DECLARE @sql NVARCHAR(100) DECLARE @db NVARCHAR(50)
SET @db = N'db1' SET @sql = N'Use ' + @db
EXEC sp_executesql @sql
Run Code Online (Sandbox Code Playgroud)
同样,它成功执行,但数据库没有改变。
我有一个表(不是我设计的),它有 20 个不同命名的列。也就是说,根据您查看的记录类型,列的适用名称可能会发生变化。
可能的列名存储在另一个表中,我可以很容易地查询。
因此,我真正要查找的查询是这样的:
SELECT Col1 AS (SELECT ColName FROM Names WHERE ColNum = 1 and Type = @Type),
Col2 AS (SELECT ColName FROM Names WHERE ColNum = 2 and Type = @Type)
FROM Tbl1
WHERE Type = @Type
Run Code Online (Sandbox Code Playgroud)
显然这行不通,那么我怎样才能得到类似的结果呢?
'
我已经尝试构建一个查询字符串并对其进行
事实证明,我使用了不正确的查询来构建动态 SQL,因此构建了一个空字符串。SQL Server 肯定正确执行了空字符串。EXECUTEing,但这只是返回“命令成功完成”并且似乎没有返回行集。
请注意,我需要这样做的原因,而不是简单地对列名进行硬编码,是因为列名是用户可配置的。
我正在查看一个对 SQL Server 使用高度动态 sql 查询的应用程序。查看以非常奇怪和复杂的方式构建的查询,但这是一个不同的故事,我告诉它是为了给我无法(太愚蠢)自己找出问题的充分理由......我看不到查询用sp_executesql.
但是当我跟踪时,我可以看到很多查询都包含在sp_executesql. 整个应用程序解决方案甚至根本不包含该命令sp_executesql。
所以我想知道是否有一种我还不知道的配置强制软件默认使用 sp_executesql 包装查询?
什么可能导致这种行为?
dynamic-sql ×10
sql-server ×8
scripting ×2
t-sql ×2
pivot ×1
postgresql ×1
query ×1
security ×1
sqlcmd ×1