eddorre

Found 2 posts tagged with 'dts'

Trials and Tribulations in Migrating Data

October 03, 2006 — 0 Comments

I seem to have lost my post “Ups and Downs” in my data migration. Oops. Oh well, I’ll try to re-iterate some of those thoughts here.

I’ve finally, after much cursing and swearing, managed to migrate the posts and comments from MSSQL to MySQL. My first attempt was through MSSQL’s DTS.

DTS to MySQL has some known bugs when dealing with fields that are BLOBs. If you’re attempting to move data using the CopyColumn method in DTS, it will fail even if you cast your column to another type. For example;

SELECT CAST) as body).

My next step was to try DTSing the file to a plain text file and then using MySQL’s Load Data command. Unfortunately, I encountered issues with this as well as it wouldn’t import my date fields correctly (it would import them as all zeros).

From there, in between the cursing, I tried various combinations of DTS and Load Data, and even some distributed queries using Linked Servers. I finally found a nugget of information on the web that allowed me to import all the data in one fell swoop.

The trick is to use DTS to export the data to a CSV file. Then using Excel, select the columns that are dates and go to Format —> Cells. Select a Custom format and then enter in yyyy-mm-dd hh:mm:ss. Re-save the CSV file and then run your Load Data command on your MySQL server.

Using this method, I was able to import all my data including dates and text fields.

How to Give a User(s) Permission to Change the Owner of a DTS Package

October 04, 2004 — 2 Comments

UPDATE: Apparently if SQL Server considers you to be dbo on the msdb database the IF (ISNULL, 0) <> 1) function will return false. It was happening to my users, so instead of using the role that I created (db_ChangeDTSOwner) I used the domain group that the user was in using this notation: “domaindomain_group”.

So the code below would read “IF (ISNULL, 0) <> 1)”. If you do not have a domain, then I would make sure that the user(s) are not part of the dbo group and they remain part of the db_ChangeDTSOwner role in the msdb database.

The simple way to do this in SQL Server 2000 is to add the user or group to the System Administrators Server Role but that breaks one of the major security tenets out there; only give a user the tools to do their job and nothing more. So I had to find another alternative. Here is what I came up with:

  1. Create a role in the msdb database called db_ChangeDTSOwner and add the users or groups that you want to this role.
Create the following stored procedures:

CREATE PROCEDURE sp_new_reassign_dtspackageowner
  name sysname,<br />&nbsp; @id UNIQUEIDENTIFIER,<br />&nbsp; @newloginname sysname<br />AS<br />&nbsp; SET NOCOUNT ON<br />&nbsp; --// First, is this a valid login?<br />&nbsp; IF SUSER_SID(newloginname) IS NULL
  BEGIN
    RAISERROR
    RETURN - Failure
  END
  -
// Does the specified package (uniquely) exist?  Referencing by name only may not be unique.
  -// We do a bit of a hack here as SQL can’t handle a DISTINCT clause with UNIQUEIDENTIFIER.
  -
// id will get the first id returned; if only name specified, see if there are more.<br />&nbsp; DECLARE @findid UNIQUEIDENTIFIER<br />&nbsp; SELECT @findid = id FROM sysdtspackages<br />&nbsp;&nbsp;&nbsp; WHERE (name IS NOT NULL OR id IS NOT NULL)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND (name IS NULL OR name = name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND (id IS NULL OR id = id)<br />&nbsp; IF @rowcount = 0
  BEGIN
    DECLARE pkgnotfound NVARCHAR(200)<br />&nbsp;&nbsp;&nbsp; DECLARE @dts_package_res NVARCHAR(100)<br />&nbsp;&nbsp;&nbsp; SELECT @pkgnotfound = FORMATMESSAGE(14599) + ' = ''' + ISNULL(name, FORMATMESSAGE) + ‘’’; ’ + FORMATMESSAGE + ’ {’
    SELECT pkgnotfound = @pkgnotfound + CASE WHEN @id IS NULL THEN FORMATMESSAGE(14589) ELSE CONVERT(NVARCHAR(50), @id) END + '}.{'<br />&nbsp;&nbsp;&nbsp; SELECT @pkgnotfound = @pkgnotfound + FORMATMESSAGE(14589) + '}'<br />&nbsp;&nbsp;&nbsp; SELECT @dts_package_res = FORMATMESSAGE(14594)<br />&nbsp;&nbsp;&nbsp; RAISERROR(14262, 16, 1, @dts_package_res, @pkgnotfound)<br />&nbsp;&nbsp;&nbsp; RETURN(1) -- Failure<br />&nbsp; END ELSE IF @name IS NOT NULL AND @id IS NULL AND<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EXISTS (SELECT * FROM sysdtspackages WHERE name = @name AND id &lt;&gt; @findid)<br />&nbsp; BEGIN<br />&nbsp;&nbsp;&nbsp; RAISERROR(14595, -1, -1, @name)<br />&nbsp;&nbsp;&nbsp; RETURN(1) -- Failure<br />&nbsp; END<br />&nbsp; SELECT @id = @findid<br />&nbsp; --// Only the owner of DTS Package ''%s'' or a member of the sysadmin role may reassign its ownership.<br />&nbsp; --// sp_add_dtspackage ensures that all versions have the same owner_sid.<br />&nbsp; IF (ISNULL(IS_MEMBER(N'db_ChangeDTSOwner'), 0) &lt;&gt; 1)<br />&nbsp; BEGIN<br />&nbsp;&nbsp;&nbsp; IF (NOT EXISTS (SELECT * FROM sysdtspackages WHERE id = @id AND owner_sid = SUSER_SID()))<br />&nbsp;&nbsp;&nbsp; BEGIN<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT @name = name FROM sysdtspackages WHERE id = @id<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RAISERROR (14585, -1, -1, @name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RETURN(1) -- Failure<br />&nbsp;&nbsp;&nbsp; END<br />&nbsp; END<br />&nbsp; --// Everything checks out, so reassign the owner.<br />&nbsp; --// Note that @newloginname may be a sql server login rather than a network user,<br />&nbsp; --// which is not quite the same as when a package is created.<br />&nbsp; UPDATE sysdtspackages<br />&nbsp;&nbsp;&nbsp; SET owner_sid = SUSER_SID(newloginname),
                owner = newloginname<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE id = @id<br />&nbsp; RETURN 0&nbsp;&nbsp;&nbsp; -- SUCCESS</div><br />The above code is an altered Microsoft stored procedure. Instead of checking to see if the user is in the System Administrators Server Role is checks to see if the user or group is in the db_ChangeDTSOwner role. <br /><br /> <div class="codeSample">CREATE&nbsp; PROCEDURE proc_DTSChangeOwner<br />package_name sysname,
old_owner sysname,<br />new_owner sysname
AS
DECLARE id uniqueidentifier, @name sysname, @error INT<br />/**<br />Author: Carlos Rodriguez<br />Date Created: 1-13-2004<br />Summary: Changes owner of DTS package so that edits can be made to it<br />ChangeLog:<br />----------------------------------------------------------------------<br />Date: 1-14-2003 <br />Author: Carlos Rodriguez<br />Change: Added logging to a table<br />----------------------------------------------------------------------<br /><br />**/<br /><br />/**<br /><br />If the package name or the old owner don't match up, display error message and stop procedure<br /><br />**/<br />IF (NOT EXISTS (SELECT * FROM msdb..sysdtspackages WHERE [owner] = @old_owner AND [name] = @package_name))<br />BEGIN<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RAISERROR('Package ''%s'' does not exist or owner name is wrong', 16, 1, @package_name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RETURN<br />END<br /><br />--First, is this a valid login?<br />&nbsp; IF SUSER_SID(new_owner) IS NULL
  BEGIN
    RAISERROR
    RETURN - Failure
  END
SET name = @package_name<br />/**<br />For each instance of a package name in the msdb..sysdtspackages table with the old owner name, let's <br />change that to the new owner name. In the msdb..sysdtspackages table, there can be multiple versions<br />of the same package so we need to do this.<br />**/<br />DECLARE cur_sysdtspackages CURSOR FOR <br />&nbsp;&nbsp; SELECT DISTINCT [name], [id]<br />&nbsp;&nbsp; FROM sysdtspackages <br />&nbsp;&nbsp; WHERE [owner] = @old_owner AND [name] = @package_name<br />&nbsp;OPEN cur_sysdtspackages<br />&nbsp;FETCH NEXT FROM cur_sysdtspackages<br />&nbsp;INTO @name, @id<br />&nbsp;WHILE @FETCH_STATUS = 0
 BEGIN
-Call undocumented stored procedure to change the owner of the package
     EXEC sp_new_reassign_dtspackageowner name=name, id=id, newloginname=new_owner
     FETCH NEXT FROM cur_sysdtspackages
     INTO name, @id<br />&nbsp;END<br />&nbsp;CLOSE cur_sysdtspackages<br />&nbsp;DEALLOCATE cur_sysdtspackages<br />--Add a record to the log (DTSChangeOwnerLog table)<br />INSERT INTO DTSChangeOwnerLog<br />VALUES(name, @old_owner, @new_owner, getdate())
GO

And finally create this table for logging:

CREATE TABLE [DTSChangeOwnerLog] (
            [record_id] [int] IDENTITY (1, 1) NOT NULL ,
            [package_name] [varchar] (100) NULL ,
            [old_owner] [varchar] (30) NULL ,
            [new_owner] [varchar] (30) NULL ,
            [dt] [datetime] NULL ,
             PRIMARY KEY  NONCLUSTERED
            (
                        [record_id]
            )  ON [PRIMARY]
) ON [PRIMARY]
GO

Remember to give the user or group execute permissions on the new stored procedures. A user can change the owner DTS package by running this code from the msdb database:

EXEC proc_DTSChangeOwner ‘name of DTS package’, ‘domainolduser’, ‘domain
ewuser’.