Reputation: 189
We received data from COBOL as below, and got to convert to SQL Server. I have followed this link
and did create the SSIS package. However i'm facing issue when converting some data from COBOL to SQL.
I marked the input columns as Bytes and Output as Numeric data as 10 and Precision 2
1.Tried creating columns as Decimal(10,2) in SQL
2.Tried it with SQL date data type for COBOL date
the package runs successfully but data is not populated. data layout
CONTRACT-SIZE pic S9(9)V99 COMP-3
DIV-REC-DATE-LOBO PIC 9(0007) COMP-3
PAR-DATE PIC S9(0007) COMP-3
BID-PRICE PIC S9(0005)V9(2) COMP-3
Tried below function to unpack, Translate, COBOLZonedPicToDecimal
Public Function Translate(ByVal str As String, sConversionTable As String) As String
Dim Temp As String, I As Int32
Temp = Space(Len(str))
For I = 1 To Len(str)
Mid(Temp, I, 1) = Mid(sConversionTable, Asc(Mid(str, I, 1)) + 1, 1)
Next
Translate = Temp
End Function
Private Function Unpack(ByVal bPacked As Byte(), ByVal iDecimalPlaces As Integer) As Decimal
Dim i As Integer
Dim HiNibble As Byte
Dim LoNibble As Byte
Dim dResult As Decimal = 0
For i = 0 To bPacked.Length - 2
UnpackNibblesToBytes(bPacked(i), LoNibble, HiNibble)
dResult = Convert.ToDecimal(dResult * 10 ^ 2I + HiNibble * 10 + LoNibble)
Next
UnpackNibblesToBytes(bPacked(bPacked.Length - 1), LoNibble, HiNibble)
dResult = dResult * 10 + HiNibble
If LoNibble = &HD& Then
dResult = -dResult
End If
Unpack = Convert.ToDecimal(dResult * 10 ^ (-iDecimalPlaces))
End Function
Private Sub UnpackNibblesToBytes(ByVal InputNibbles As Byte, ByRef LoNibble As Byte, ByRef HiNibble As Byte)
LoNibble = (Me.F And InputNibbles)
HiNibble = ((Me.F0 And InputNibbles) >> 4)
End Sub
Public Function DecimalToCOBOLZonedPic(ByVal dNumber As Decimal, ByVal iPadLength As Integer, ByVal iDecimalPlaces As Integer, ByVal bModifiedZoned As Boolean) As String
Dim isNegative As Boolean = False
Dim strNumber As String
Dim sPositive As String = "{ABCDEFGHI"
Dim sNegativeMod As String = "}JKLMNOPQR"
Dim sNegativeStrict As String = "pqrstuvwxy"
' Determine the sign
If dNumber < 0 Then
isNegative = True
dNumber = -dNumber
End If
dNumber = Convert.ToDecimal(dNumber * (10 ^ iDecimalPlaces))
strNumber = dNumber.ToString
If strNumber.IndexOf(".") > -1 Then
' Truncate remaining decimal places
strNumber = strNumber.Substring(0, strNumber.IndexOf("."))
End If
' Pad with leading zeros
If strNumber.Length < iPadLength Then
strNumber = strNumber.PadLeft(iPadLength, "0"c)
End If
Dim lastDigit As Integer = Convert.ToInt32(strNumber.Substring(strNumber.Length - 1, 1))
If bModifiedZoned Then
If isNegative Then
strNumber = strNumber.Substring(0, strNumber.Length - 1) & sNegativeMod.Substring(lastDigit, 1).ToString
Else
strNumber = strNumber.Substring(0, strNumber.Length - 1) & sPositive.Substring(lastDigit, 1).ToString
End If
Else
If isNegative Then
strNumber = strNumber.Substring(0, strNumber.Length - 1) & sNegativeStrict.Substring(lastDigit, 1).ToString
End If
End If
Return strNumber
End Function
Public Function COBOLZonedPicToDecimal(ByVal strNumber As String, ByVal decimalPlaces As Integer) As Decimal
Dim sZoneChar As String
Dim convertedNumber As Decimal
Dim sPositive As String = "{ABCDEFGHI"
Dim sNegativeMod As String = "}JKLMNOPQR"
Dim sNegativeStrict As String = "pqrstuvwxy"
strNumber = strNumber.Trim
If strNumber = "" Then
Return 0
End If
sZoneChar = strNumber.Substring(strNumber.Length - 1)
Select Case True
Case sPositive.IndexOf(sZoneChar) > -1
strNumber = strNumber.Substring(0, strNumber.Length - 1) & sPositive.IndexOf(sZoneChar)
convertedNumber = Convert.ToDecimal(strNumber)
Case sNegativeMod.IndexOf(sZoneChar) > -1
strNumber = strNumber.Substring(0, strNumber.Length - 1) & sNegativeMod.IndexOf(sZoneChar)
convertedNumber = -Convert.ToDecimal(strNumber)
Case sNegativeStrict.IndexOf(sZoneChar) > -1
strNumber = strNumber.Substring(0, strNumber.Length - 1) & sNegativeStrict.IndexOf(sZoneChar)
convertedNumber = -Convert.ToDecimal(strNumber)
Case Else
convertedNumber = Convert.ToDecimal(strNumber)
End Select
Return Convert.ToDecimal(convertedNumber / (10 ^ decimalPlaces))
End Function
Upvotes: 1
Views: 3080
Reputation: 10543
0x0200EAA4 converted into EBCDIC is x0200529F which is a valid comp-3 value (2020-May-29).
Running an ascii conversion on a binary EBCDIC file (like this file) will corrupt the File Do not try and process the current file.
Convert the file to Text on the source compute (Mainframe ??) and transmit/translate the file
If processing a Mainframe Cobol File have a look at cb2xml. It will convert a Cobol Copybook into a Xml file (and calculate position / length). The Xml can be processed in many languages.
Convert to fixed length on source compute (probably is already Fixed length) and transfer as an EBCDIC file. The file will not have any carriage return line-Feed characters in it. You would need to process it as an EBCDIC file.
If you can
Some thing like CobolToCsv can convert the file from Cobol-Ebcdic into an Ascii-Csv file
There are multiple EBCDIC character-sets Cp037/IBM037 is US EBCDIC; CP273/IBM273 is German EBCDIC you will need to find out which EBCDIC dialect is being used
Note: CP037 stands for Coded-Page 037
With mainframe fixed width, all records are the same length and there are no Carriage Return / Line Feed characters. For a file with 26 byte records it is
<-- 26 bytes --><-- 26 bytes --> ... <-- 26 bytes -->
cb2xml will convert a Cobol Copybook to xml. This allows for generic processing of Cobol data in most modern languages
cb2xml will convert
01 Location-Record.
03 Record-Type pic xx.
03 location occurs 10.
05 DC-Number pic 9(4).
05 Pack-Quantity pic 9(8).
to
<item display-length="122" level="01" name="Location-Record" position="1" storage-length="122">
<item display-length="2" level="03" name="Record-Type" picture="xx" position="1" storage-length="2"/>
<item display-length="12" level="03" name="location" occurs="10" position="3" storage-length="12">
<item display-length="4" level="05" name="DC-Number" numeric="true" picture="9(4)" position="3" storage-length="4"/>
<item display-length="8" level="05" name="Pack-Quantity" numeric="true" picture="9(8)" position="7" storage-length="8"/>
</item>
</item>
Upvotes: 2