-1

I'm doing a MSSQL to MySQL data migration. My date/time value is exactly how it needs to be in both databases. However, VBScript converts this (by default):

2016-01-06 10:26:30.363

To this (which errors on INSERT):

1/6/2016 10:26:30 AM

I'm aware I can construct the value again with Year(), Month(), etc. Anyone know how to get this date/time value unaltered from the database using VBScript?

UPDATE: Per the "show my code" comment, here's a section:

strSQL = "SELECT * FROM Users"
Set objRS = CreateObject("ADODB.RecordSet") 
objRS.Open strSQL, objConn,3,3

Do While Not objRS.EOF

    sUserId = objRS("UserId")
    sCreatedDate = objRS("CreatedDate") '<-- At this point, it's "converted" already
    wscript.echo sCreatedDate      '<-- This displays 1/6/2016 10:26:30 AM format

    insertSQL = "INSERT INTO northwind.usersetting (UserId,CreatedDate) "
    insertSQL = insertSQL & "VALUES ('"&sUserId&"','"&sCreatedDate &"');"

    objConn2.Execute = (insertSQL)

objRS.MoveNext
Loop

Just your standard vbscript. I think I can get away with this in MSSQL, but MySQL doesn't like it. In the meantime, I have done this to work around the issue:

Function FormatDate4Insert(date)
    FormatDate4Insert = Year(date) & "-" & Month(date) & "-" & Day(date) & " " & Hour(date) & ":" & Minute(date) & ":" & Second(date)
End Function

I would love to do a straight non-conversion, but vbs seems to convert no matter what I do. I tried converting to string and a few other things with no joy...

P.S. I'm not sure what you mean by database import export mechanisms. However, I tried the MySQL migration tool as well as exporting and import mechanisms (to csv...with different delimiters and such... and even a json export, massaging the data with Notepad++ and Excel, etc) and can't get the data to jive with my selective import. I can migrate an entire database without issue for the most part, but simply want to do the data from an individual table. When I kill too much time, I usually just fall back to vbscript or whatever scripting makes sense.

I find both databases more forgiving and finicky in some areas. However, with MSSQL to MySQL, I have to convert empty values to "NULL" and True/False to their bit values (e.g. b'0') and other little tweaks that scripting makes easier (at least for me).

UPDATE 2: The error as requested:

Microsoft OLE DB Provider for ODBC Drivers: [MySQL][ODBC 8.0(w) Driver][mysqld-8.0.16]Incorrect datetime value: '1/6/2016 10:26:30 AM' for column 'CreatedDate' at row 1.

I can't reproduce the other error, but I was also getting an error that was something similar to this:

ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1/6/2016 10:26:30 AM'

That was in reference to the Insert statement.

Sum None
  • 2,164
  • 3
  • 27
  • 32
  • 1
    If you're using database export and import mechanisms VBScript shouldn't be touching the data at all. Please show your code. – Ansgar Wiechers Jul 26 '19 at 07:21
  • Don't do what you're doing. [Export](https://stackoverflow.com/q/44606889/1630171) the data as a CSV from SQL Server and [import](https://stackoverflow.com/q/3635166/1630171) that CSV into MySQL. Use VBScript only if you need to make adjustments to the CSV before import. – Ansgar Wiechers Jul 27 '19 at 22:41
  • @AnsgarWiechers As I mentioned above, that's what I tried (for two days) and couldn't get the data to jive between the two dbs. There's a couple columns deleted and a couple columns added. But, I basically ran out of ideas doing that. Furthermore, importing as json would say everything imported successfully, and then "0 records imported" on the next screen. I guess I could start another SO question on the errors I was getting for the import, but I've basically already finished what I needed to do. – Sum None Jul 28 '19 at 02:07

1 Answers1

0

Try a parameterized query:

    ' *** ADO ***
    '---- CommandTypeEnum Values ----
    Const adCmdText = &H0001

    '---- DataTypeEnum Values ----
    Const adInteger = 3
    Const adDate = 7

    '---- ParameterDirectionEnum Values ----
    Const adParamInput = &H0001

    Dim cmd
    Dim sSQL

    Set cmd = CreateObject("ADODB.Command")
    Set cmd.ActiveConnection = cn   ' Assumes cn is an actice ADOB.Connection object
    cmd.CommandType = adCmdText

    sSQL = "INSERT INTO northwind.usersetting (UserId, CreatedDate) VALUES (?, ?);"

    cmd.CommandText = sSQL

    Set prm = cmd.CreateParameter("UserId", adInteger, adParamInput, , UserId)  ' Assuming UserId is a integer, adjust as needed
    cmd.Parameters.Append prm

    Set prm = cmd.CreateParameter("CreatedDate", adDate, adParamInput, , CreatedDate)
    cmd.Parameters.Append prm

    cmd.Execute , , adExecuteNoRecords

[Added]

Try the following snippet just to make sure that MySQL accepts a date value:

Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = cn   ' Assumes cn is an actice ADOB.Connection object
cmd.CommandType = adCmdText

sSQL = "INSERT INTO northwind.usersetting (CreatedDate) VALUES (?);"

cmd.CommandText = sSQL

Set prm = cmd.CreateParameter("CreatedDate", adDate, adParamInput, , Now())
cmd.Parameters.Append prm

cmd.Execute , , adExecuteNoRecords

If this works, than you might want to try the following line in the first sample I posted:

Set prm = cmd.CreateParameter("CreatedDate", adDate, adParamInput, , CDate(CreatedDate))

Note the explicit date conversion with CDate().

The ADO constants at the top of the first code snippet are taken from a file called adovbs.inc, distributed by Microsoft. Unfortunately a quick search didn't bring up a download from MS. But here's a gist with its contents. Scroll down to '---- DataTypeEnum Values ----. There are a few other date related constants, e.g. Const adDBDate = 133. You might try out those and see if it yields the expected result.

[Added 2]

' *** ADO ***
'---- CommandTypeEnum Values ----
Const adCmdText = &H0001

'---- DataTypeEnum Values ----
Const adInteger = 3
Const adDate = 7

'---- ParameterDirectionEnum Values ----
Const adParamInput = &H0001


Dim strSQL
Dim cmd, rs


Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = cnMSSQL   ' Assumes cnMSSQL is an actice ADOB.Connection object connected to the MS SQL server
cmd.CommandType = adCmdText

' Fill the recordset from a command object connecting to the source MS SQL
strSQL = "SELECT * FROM Users"
cmd.CommandText = strSQL
Set rs = cmd.Execute()

' Now use the Command object to fill the MySQL DB
Set cmd.ActiveConnection = cnMySQL  ' ' Assumes cnMySQL is an actice ADOB.Connection object connected to the MySQL server
strSQL = "INSERT INTO northwind.usersetting (UserId, CreatedDate) VALUES (?, ?);"
cmd.CommandText = strSQL

Do While Not rs.EOF

    ' This assumes that the columns in source MS SQL also are named 'UserId' and 'CreateDate'.
    ' Adjust the rs.Fields("UserId").Value and rs.Fields("CreateDate").Value as needed

    Set prm = cmd.CreateParameter("UserId", adInteger, adParamInput, , rs.Fields("UserId").Value)  ' Assuming UserId is a integer, adjust as needed
    cmd.Parameters.Append prm

    Set prm = cmd.CreateParameter("CreatedDate", adDate, adParamInput, , rs.Fields("CreateDate").Value)
    cmd.Parameters.Append prm

    cmd.Execute , , adExecuteNoRecords  

    ' Clear/reset the parameter collection

    rs.MoveNext

Loop
Hel O'Ween
  • 1,423
  • 9
  • 15
  • Thanks, this appears to be for the `INSERT` portion, whereas the issue seems to be in retrieving the data, as it's already "converted" to the non-desired format by the time it hits your portion of the code. So when I do `wscript.echo prm.Value` it comes back `1/6/2016 10:26:30 AM.` Furthermore, I tried using ADO to retrieve (i.e. `SELECT`) the data and still getting the `1/6/2016 10:26:30 AM` format as well. – Sum None Jul 26 '19 at 22:40
  • Don't get fooled by the _visual_ output of a date data type. It uses your locale settings to determine the formatting, e.g. `MsgBox Now()` on _my_ machine results in `29.07.2019 16:00:07`, which is the correct localized date format. Also: parameterized queries work on any SQL statement. To retrieve the results just change `cmd.Execute` to `Set rs = cmd.Execute()`. – Hel O'Ween Jul 29 '19 at 14:05
  • That's interesting. I never would have thought of that. But, seems you're correct. When I do `MsgBox Now()`, I get that undesired format. So, where are those locale settings to change it so it behaves like yours? The latter of your statement is basically what I did and no go, because it's feeding that undesired format into the `INSERT` statement every time (i.e. I can see it in the error message and has always been the issue). Therefore, it appears my computer's visual representation of that data is what's actually being attempted... – Sum None Jul 30 '19 at 13:49
  • OK, just to make sure: the column in both DBs is of a date data type? If so, which ones. I ask, because a date data type in itself has no "format". What you see, is always just the visual representation of the _value_. E.g. the `Date` data type in VB6/VBA is actually a `Double`, with the whole number representing the date part and the decimal digits the time part. You also mentioned an error message, can you update your OP with it? – Hel O'Ween Jul 30 '19 at 15:58
  • Yes, both are date types. MSSQL = datetime... MySQL = DATETIME(6). I will update my original question with the error. – Sum None Jul 31 '19 at 00:22
  • I've updated my answer with a suggestion to narrow down the problem. – Hel O'Ween Jul 31 '19 at 15:48
  • I'm getting lost here.. `Now()`, `CDate(sCreatedDate)` as well as `sCreatedDate` (unaltered) are all successful now when inserting with the code above. However, they are ALL in this format now (in MySQL)... `'2017-04-29 00:00:00.000000'` I also created a new db to test this and not muck up my project db, so I wonder if the issue is not related to my other (target) db... I'm going to have to compare settings (or compare settings in your code above)... however, you know how to get the time in there too? I think if we can get that, we can just call this solved. – Sum None Aug 01 '19 at 12:05
  • You have no doubt some date to string conversion going on inbetween. If the source column has a time, the target column should also include it. I've update my answer with a code sample that uses the ADODB.Command object for both retrieving and storing the data. Note that it doesn't store the values retrieved from the MS SQL server first in a variable, but utilizes `rs.Fields().Value` directly to "feed" into the MySQL DB in order to prevent any under-the-hood type conversion going on. – Hel O'Ween Aug 02 '19 at 15:33