【问题标题】:programmatically generate script for a table以编程方式为表生成脚本
【发布时间】:2018-04-17 12:37:26
【问题描述】:

我学会了如何为表格生成脚本。

例如这个表:

生成这样的脚本(我省略了一些东西):

CREATE TABLE [dbo].[singer_and_album](
    [singer] [varchar](50) NULL,
    [album_title] [varchar](100) NULL
) ON [PRIMARY]
GO

INSERT [dbo].[test_double_quote] ([singer], [album_title]) VALUES (N'Adale', N'19')
GO

INSERT [dbo].[test_double_quote] ([singer], [album_title]) VALUES (N'Michael Jaskson', N'Thriller"')
GO

我尝试使用this shell code 以编程方式生成脚本。并得到错误:

PS SQLSERVER:\SQL\DESKTOP-KHTRJOJ\MSSQL\Databases\yzhang\Tables\dbo.test_double_quote> C:\Users\yzhang\Documents\script_out_table.ps1 "DESKTOP-KHTRJOJ\MSSQL" "yzhang" "dbo" "test_double_quote", "C:\Users\yzhang\Documents\script_out.sql"

为“EnumScript”和参数找到多个模棱两可的重载 计数:“1”。在 C:\Users\yzhang\Documents\script_out_table.ps1:41 字符:16 + foreach ($s in $scripter.EnumScript($tbl.Urn)) { write-host $s } + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest

有人可以帮忙吗?我对壳牌了解不多。 顺便说一句,shell 是生成脚本的唯一方法吗?我们可以用一些sql代码来做吗?谢谢--


仅供参考,请参阅this 了解如何手动生成脚本。在我的情况下(sql server 2016 management studio)就像

  1. 右键数据库名(不是表名)->Tasks->Generate scripts

  1. 选择一个表或所有表

  2. 单击advanced 并选择schema and data

【问题讨论】:

  • 您可以编写哪些编程语言,以便我们提供替代方案。
  • 谢谢@ImranAliKhan。我熟悉 Python/R/sql。如果有人能告诉我如何更改shell代码,那也很好(我不太了解shell,所以我会机械地使用它)
  • 查看我的更新答案
  • article where you got the Powershell script 底部有一些 cmets 讨论了“多重重载”错误以及它们如何通过删除 .Urn 参考来修复:foreach ($s in $scripter.EnumScript($tbl))

标签: sql-server copy


【解决方案1】:

这是一个生成表格脚本的sql脚本

declare @vsSQL varchar(8000)
declare @vsTableName varchar(50)
select @vsTableName = '_PRODUCT'--- Your Table Name here

select @vsSQL = 'CREATE TABLE ' + @vsTableName + char(10) + '(' + char(10)

select @vsSQL = @vsSQL + ' ' + sc.Name + ' ' +
st.Name +
case when st.Name in ('varchar','varchar','char','nchar') then '(' + cast(sc.Length as varchar) + ') ' else ' ' end +
case when sc.IsNullable = 1 then 'NULL' else 'NOT NULL' end + ',' + char(10)
from sysobjects so
join syscolumns sc on sc.id = so.id
join systypes st on st.xusertype = sc.xusertype
where so.name = @vsTableName
order by
sc.ColID

select substring(@vsSQL,1,len(@vsSQL) - 2) + char(10) + ')'

编辑: c# 代码

public string GetScript(string strConnectionString
                      , string strObject
                      , int ObjType)
{
    string strScript = null;
    int intCounter = 0;
    if (ObjType != 0)
    {
        ObjSqlConnection = new SqlConnection(strConnectionString.Trim());

        try
        {
            ObjDataSet = new DataSet();
            ObjSqlCommand = new SqlCommand("exec sp_helptext 
                [" + strObject + "]", ObjSqlConnection);
            ObjSqlDataAdapter = new SqlDataAdapter();
            ObjSqlDataAdapter.SelectCommand = ObjSqlCommand;
            ObjSqlDataAdapter.Fill(ObjDataSet);

            foreach (DataRow ObjDataRow in ObjDataSet.Tables[0].Rows)
            {
                strScript += Convert.ToString(ObjDataSet.Tables[0].Rows[intCounter][0]);
                intCounter++;
            }
        }
        catch (Exception ex)
        {
           strScript = ex.Message.ToString();
        }
        finally
        {
            ObjSqlDataAdapter = null;
            ObjSqlCommand = null;
            ObjSqlConnection = null;
        }
    }

    return strScript;
}

要创建插入脚本,请使用此存储过程

IF EXISTS (SELECT * FROM dbo.sysobjects 
WHERE id = OBJECT_ID(N'[dbo].[InsertGenerator]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1)
DROP PROCEDURE [dbo].[InsertGenerator]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO

CREATE PROC [dbo].[InsertGenerator]
(
@tableName varchar(100),
@KeyColumn1 varchar(100)='',
@KeyColumn2 varchar(100)=''
)
AS

-- Generating INSERT statements in SQL Server
-- to validate if record exists - supports 2 field Unique index

--Declare a cursor to retrieve column specific information for the specified table
DECLARE cursCol CURSOR FAST_FORWARD FOR 
SELECT column_name,data_type FROM information_schema.columns WHERE table_name = @tableName

OPEN cursCol

DECLARE @string nvarchar(max) --for storing the first half of INSERT statement
DECLARE @stringData nvarchar(max) --for storing the data (VALUES) related statement
DECLARE @dataType nvarchar(1000) --data types returned for respective columns
DECLARE @FieldVal nvarchar(1000) -- save value for the current field
DECLARE @KeyVal nvarchar(1000) -- save value for the current field
DECLARE @KeyTest0 nvarchar(1000) -- used to test if key exists
DECLARE @KeyTest1 nvarchar(1000) -- used to test if key exists
DECLARE @KeyTest2 nvarchar(1000) -- used to test if key exists

SET @KeyTest0=''

IF @KeyColumn1<>''
SET @KeyTest0='IF not exists (Select * from '+@tableName

SET @KeyTest1=''
SET @KeyTest2=''

SET @string='INSERT '+@tableName+'('
SET @stringData=''
SET @FieldVal=''
SET @KeyVal=''

DECLARE @colName nvarchar(50)

FETCH NEXT FROM cursCol INTO @colName,@dataType

IF @@fetch_status<>0
begin
    print 'Table '+@tableName+' not found, processing skipped.'
    close curscol
    deallocate curscol
    return
END

WHILE @@FETCH_STATUS=0
BEGIN

IF @dataType in ('varchar','char','nchar','nvarchar')
BEGIN
    SET @FieldVal=''''+'''+isnull('''''+'''''+'+@colName+'+'''''+''''',''NULL'')+'',''+'
    SET @KeyVal='''+isnull('''''+'''''+'+@colName+'+'''''+''''',''NULL'')+'',''+'
    SET @stringData=@stringData+@FieldVal
END

ELSE

if @dataType in ('text','ntext','xml') --if the datatype is text or something else 
BEGIN
    SET @FieldVal='''''''''+isnull(cast('+@colName+' as varchar(max)),'''')+'''''',''+'
    SET @stringData=@stringData+@FieldVal
END
ELSE
IF @dataType = 'money' --because money doesn't get converted from varchar implicitly
BEGIN
    SET @FieldVal='''convert(money,''''''+isnull(cast('+@colName+' as varchar(200)),''0.0000'')+''''''),''+'
    SET @stringData=@stringData+@FieldVal
END
ELSE 
IF @dataType='datetime'
BEGIN
    SET @FieldVal='''convert(datetime,'+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+',121)+'''''+''''',''NULL'')+'',121),''+'
    SET @stringData=@stringData+@FieldVal
END
ELSE 
IF @dataType='image' 
BEGIN
    SET @FieldVal='''''''''+isnull(cast(convert(varbinary,'+@colName+') as varchar(6)),''0'')+'''''',''+'
    SET @stringData=@stringData+@FieldVal
END
ELSE --presuming the data type is int,bit,numeric,decimal 
BEGIN
    SET @FieldVal=''''+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+')+'''''+''''',''NULL'')+'',''+'
    SET @KeyVal='''+isnull('''''+'''''+convert(varchar(200),'+@colName+')+'''''+''''',''NULL'')+'',''+'
    SET @stringData=@stringData+@FieldVal
END

--Build key test
IF @KeyColumn1=@colName
begin
    SET @KeyTest1 = ' WHERE [' + @KeyColumn1 + ']='
    SET @KeyTest1 = @KeyTest1+@KeyVal+']'
end
IF @KeyColumn2=@colName
begin
    SET @KeyTest2 = ' AND [' + @KeyColumn2 + ']='
    SET @KeyTest2 = @KeyTest2+@KeyVal+']'
end

SET @string=@string+'['+@colName+'],'

FETCH NEXT FROM cursCol INTO @colName,@dataType
END

DECLARE @Query nvarchar(max)

-- Build the test string to check if record exists
if @KeyTest0<>''
begin
    if @Keycolumn1<>''
        SET @KeyTest0 = @KeyTest0 + substring(@KeyTest1,0,len(@KeyTest1)-4)
    if @Keycolumn2<>''
    begin
        SET @KeyTest0 = @KeyTest0 + ''''
        SET @KeyTest0 = @KeyTest0 + substring(@KeyTest2,0,len(@KeyTest2)-4)
    end
    SET @KeyTest0 = @KeyTest0 + ''')'

    SET @query ='SELECT '''+substring(@KeyTest0,0,len(@KeyTest0)) + ') ' 
end
else
    SET @query ='SELECT '''+substring(@KeyTest0,0,len(@KeyTest0))

SET @query = @query + substring(@string,0,len(@string)) + ') ' 
SET @query = @query + 'VALUES(''+ ' + substring(@stringData,0,len(@stringData)-2)+'''+'')'' FROM '+@tableName

exec sp_executesql @query

CLOSE cursCol
DEALLOCATE cursCol

GO

并像下面这样使用 InsertGenerator

DECLARE @return_value int

EXEC    @return_value = [dbo].[InsertGenerator]
        @tableName = N'_PRODUCT'

SELECT  'Return Value' = @return_value

【讨论】:

  • 非常感谢@ImranAliKhan。我建议您将 c# 代码留在那里,以便对其他人有所帮助。我测试了这段代码,它生成的代码可以完美地制作表模式,但不会插入数据。如果可能的话,您能否也添加那部分?一个可能更大的问题是,输出字符串是一个变量 - 我的数据有 20G 我担心长度。我也会对此做一些研究。非常感谢-
猜你喜欢
  • 1970-01-01
  • 2012-01-08
  • 2010-12-14
  • 2011-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多