0

我很少使用 SQL Server,并且在专业环境中我很清楚!我正在做一个宠物项目,但我在创建脚本时遇到了问题。

我有一个在线数据库,我需要从中提取所有内容。我使用 SQL Server Management Studio 中的任务 > 生成脚本选项。以下是脚本创建的一个插入语句的示例(我有 1,000 个这样的插入语句):

INSERT [dbo].[NewComics] ([NewComicId], [Title], [Subtitle], [ReleaseDate], [CollectionId]) VALUES (366, N'Hawk & Dove 1:                                                                                      ', N'First Strikes                                                                                       ', CAST(0x00009F6F00000000 AS DateTime), 248)

我对此有两个问题:

(a) 我想从两个标题元素中删除所有空格 (b) 我不想要 HEX 日期 - 我想要像 2006-09-01 (yyyy-mm-dd) 这样的可读内容

INSERT [dbo].[NewComics] ([NewComicId], [Title], [Subtitle], [ReleaseDate], [CollectionId]) VALUES (366, N'Hawk & Dove 1:', N'First Strikes', '2006-09-01', 248)

将大约 3,000 个插入语句更改为这种修订格式的最快方法是什么?

仅供参考 - 这是桌子的设计:

[NewComicId] [int] NOT NULL,
[Title] [nchar](100) NOT NULL,
[Subtitle] [nchar](100) NULL,
[ReleaseDate] [datetime] NOT NULL,
[CollectionId] [int] NOT NULL,

提前致谢!

4

2 回答 2

5

是的,生成脚本可悲地将日期时间列编写为 CONVERT(binary_value, Datetime)。我会尝试回答为什么(或者更重要的是,如果有办法改变行为)。我怀疑原因是为了避免在具有不同语言环境/区域设置等的不同机器上运行脚本时出现任何问题。我不知道是否有办法在此期间改变这种情况,但 Management Studio 不是编写数据脚本的唯一方法...您可以查看第三方产品,例如 Red-Gate 的 SQL 数据比较。

如果它真的只有 3,000 行,并且您打算在不同的服务器上运行生成的脚本,请停止使用向导并执行此操作(乍一看,这看起来很可怕,但它会执行您想要的几件事 - 输出脚本准备好复制、粘贴和运行,具有格式良好且可读的日期,以 1000 为单位批量插入多行 VALUES,中间使用 GO 命令,甚至可以处理标题、副标题和 collectionid 中潜在的 NULL 值):

DECLARE @newtable SYSNAME = 'dbo.NewComics';

SET NOCOUNT ON;

;WITH x AS (SELECT TOP (4000) s = '(' 
    + CONVERT(VARCHAR(12), NewComicId) + ','
    + COALESCE('N''' + REPLACE(RTRIM(Title), '''', '''''') + '''', 'NULL') + ',' 
    + COALESCE('N''' + REPLACE(RTRIM(SubTitle), '''', '''''') + '''', 'NULL') 
    + ', ''' + CONVERT(CHAR(8), ReleaseDate, 112) + ' '
    + CONVERT(CHAR(8), ReleaseDate, 108) + ''','
    + CONVERT(VARCHAR(12), COALESCE(CollectionId, 'NULL')) + ')',
  rn = ROW_NUMBER() OVER (ORDER BY NewComicId)
  FROM dbo.OldComics ORDER BY NewComicId
),
y AS
(
SELECT [/*a*/] = 1, [/*b*/] = 'SET NOCOUNT ON;
GO
INSERT ' + @newtable + ' VALUES'
UNION ALL 
SELECT 2, s = CASE WHEN rn > 1 THEN ',' ELSE '' END + s
 FROM x WHERE rn BETWEEN 1 AND 1000
UNION ALL 
SELECT 3, 'GO' UNION ALL 
SELECT 4, s = CASE WHEN rn > 1001 THEN ',' ELSE '' END + s
 FROM x WHERE rn BETWEEN 1001 AND 2000
UNION ALL 
SELECT 5, 'GO' UNION ALL 
SELECT 6, s = CASE WHEN rn > 2001 THEN ',' ELSE '' END + s
 FROM x WHERE rn BETWEEN 2001 AND 3000
UNION ALL 
SELECT 7, 'GO' UNION ALL 
SELECT 8, s = CASE WHEN rn > 3001 THEN ',' ELSE '' END + s
 FROM x WHERE rn BETWEEN 3001 AND 4000
)
SELECT [/*b*/] FROM y ORDER BY [/*a*/];

(如果你正好有 3000 或 3001 行,你可能不得不使用它,或者如果你有超过 4000 行,则添加另外几个联合,等等。)

如果要将数据移动到同一实例上的不同表或不同数据库,请使用 @swasheck 提供的脚本(同样,停止使用向导)。

您可能已经注意到这里的一个共同趋势:如果您不喜欢它为 dates 输出的二进制格式,请停止使用生成脚本向导

于 2012-05-31T20:44:30.867 回答
2

所以如果这是我,我会做的是在一个单独的数据库中建立表结构:

CREATE TABLE NewComics (
[NewComicId] [int] identity (0,1) NOT NULL,
[Title] [nvarchar](100) NOT NULL,
[Subtitle] [nvarchar](100) NULL,
[ReleaseDate] [datetime] NOT NULL,
[CollectionId] [int] NOT NULL
);

ALTER TABLE [NewComics]
ADD CONSTRAINT PK_NewComicsID PRIMARY KEY;

然后使用 SQL 清理数据,如下所示:

INSERT INTO [NewDatabase].[dbo].[NewComics] (Title, Subtitle, ReleaseDate, CollectionID) 
SELECT 
    LTRIM(RTRIM(Title))
    , LTRIM(RTRIM(Subtitle))
    , CAST(ReleaseDate as Datetime)
    , CollectionID 
FROM [OldDatabase].[dbo].[NewComics];

或者,您可以使用相同的SELECT查询:

SELECT 
    NewComicID
    , LTRIM(RTRIM(Title))
    , LTRIM(RTRIM(Subtitle))
    , CAST(ReleaseDate as Datetime)
    , CollectionID 
FROM [OldDatabase].[dbo].[NewComics];

作为导入/导出数据任务的源(在您习惯的同一菜单中Generate Scripts)。[OldDatabase]在此服务器上将是源,[NewDatabase]在此服务器上将是目标。确保选中所有身份插入的框。

于 2012-05-31T19:07:04.963 回答