cancel
Showing results for 
Search instead for 
Did you mean: 
Subscribe

If you have a table with a varchar column containing different kinds of values (int, date, string, float) all converted to a string and you then want to join the int value to a different table. I'm getting errors like "Cannot convert "some date value" to a numeric".

Setup the tables:

CREATE TABLE "DBA"."TestData" (
    "FieldName" VARCHAR(10) NULL,
    "TestData" VARCHAR(10) NULL
) IN "system";

INSERT INTO "DBA"."TestData" ("FieldName","TestData") VALUES('Id','1');
INSERT INTO "DBA"."TestData" ("FieldName","TestData") VALUES('OtherId','1');
INSERT INTO "DBA"."TestData" ("FieldName","TestData") VALUES('Date','2015-01-01');
INSERT INTO "DBA"."TestData" ("FieldName","TestData") VALUES('Text','Bla');
INSERT INTO "DBA"."TestData" ("FieldName","TestData") VALUES('Float','1.15')

CREATE TABLE "DBA"."JoinId" (
    "Id" INTEGER NULL
) IN "system";

INSERT INTO "DBA"."JoinId" ("Id") VALUES(1);
INSERT INTO "DBA"."JoinId" ("Id") VALUES(2);

CREATE FUNCTION "DBA"."IsIntegerValue1"(string VarChar(10))
returns bit
begin
  declare isInt bit;

  if string = '1' then 
    set isInt = 1
  else
    set isInt = 0
  endif;

  return isInt;
end;

The result I am looking for:

FieldName | TestData   | Id
-----------------------------
Id        | 1          | 1
OtherId   | 1          | NULL
Date      | 2015-01-01 | NULL
Text      | Bla        | NULL
Float     | 1.15       | NULL

The queries:

SQL 1:

select *
  from TestData
       left outer join JoinId
                    on JoinId.Id = if TestData.Fieldname = 'Id' then TestData.TestData else null endif

SQL 2:

select *
  from TestData
       left outer join JoinId
                    on TestData.Fieldname = 'Id'
                   and JoinId.Id = if IsNumeric(TestData.TestData) = 1 then TestData.TestData else null endif

SQL 3:

select *
  from TestData
       left outer join JoinId
                    on TestData.Fieldname = 'Id'
                   and JoinId.Id = if IsNumeric(TestData.TestData) = 1 then TestData.TestData else null endif

SQL 4:

select *
  from TestData
       left outer join JoinId
                    on TestData.Fieldname = 'Id'
                   and Id = if IsIntegerValue1(TestData) = 1 then TestData else null endif

Result 1, 2, 3 and 4:

Cursor not in a valid state
SQLCODE=-853, ODBC 3 State="24000"

Cannot convert '2015-01-01' to a numeric
SQLCODE=-157, ODBC 3 State="07006"

SQL 5:

select *
  from TestData
       left outer join JoinId
                    on TestData.Fieldname = 'Id'
                   and JoinId.Id = if IsNumeric(TestData.TestData) = 1 and IsDate(TestData.TestData) = 0 then TestData.TestData else null endif

Result 5: This doesn't crash but it doesn't give the result I am looking for (as expected because IsDate('1') returns true)

My questions:

  • Why are SQL 1, 2, 3 and 4 crashing and not SQL 5?
  • How can I get the desired result?

Extra note: In the actual case I'm using this for I could really use the available PK/FK indexes for performance reasons and I would rather not create additional indexes like "cast(JoinId.Id as varchar)" as suggested in Volkers answer.

Tested with ASA 16.0.0.2283

View Entire Topic
VolkerBarth
Contributor
0 Likes

What version do you use?

With 12.0.1.4403, all 5 queries do succeed and do return the desired result (although queries 2 and 3 look similar to me...).

That being said, in general when the query engine seems to try to do undesired casts and fails, I'd usually try to adapt the "comparison goal" accordingly, such as

select *
   from TestData
      left outer join JoinId
         on TestData.Fieldname = 'Id'
         and cast(JoinId.Id as varchar) = TestData.TestData

That would even work if you would attempt to join over a different row that has no int value, such as TestData.Fieldname = 'Date'.

Chris26
Participant
0 Likes

Tested with ASA 16.0.0.2283

I should have added that in the actual case I'm using this for I could really use indexes for performance reasons and I would rather not create an index on "cast(JoinId.Id as varchar)".

VolkerBarth
Contributor
0 Likes

Ah, I see, with 16.0.0.2270 I do the errors for queries 1-4, too.

However, for me query 5 the result seems fitting.


Here's another attempt by building a derived query just with the "comparable rows" and then join that with JoinId. That may or may not help in your real case, that's difficult to tell without knowing that case...

select TestData.*, JoinId.*
   from TestData
      left join
         (select * from TestData where Fieldname = 'Id') TestDataWithId
          on TestData.FieldName = TestDataWithId.FieldName
      left outer join JoinId
         on TestDataWithId.TestData = JoinId.Id
Chris26
Participant
0 Likes

In the result for query 5 I get the "Id" column contains only "NULL" values. Where I need a value "1" in that column for the record with "FieldName" = "Id".

Your attempt looks promising. I would need to see if that leads to acceptable results (if it's not too slow)

However I hope that someone from SAP will react on this, and explain what is happening here and why this seems to work with version 12 and not with 16.

VolkerBarth
Contributor
0 Likes

FWIW, with 16.0.0.2270, query 5 returns the desired result set for me:


Re Auto convert and join

Chris26
Participant
0 Likes

Thats strange... In that first row I'm getting Id = NULL

If I try

select IsNumeric('1') as IsNumeric, IsDate('1') as IsDate

The result is

IsNumeric | IsDate
------------------
1         | 1

Then I'm guessing IsDate('1') is returning 0 for you?

VolkerBarth
Contributor
0 Likes

Yes, I'm getting

1,0

here. Note, I'm running with German locale but with default date_format = 'YYYY-MM-DD' and default date_order = 'YMD'.

According, the following cast fails with SQLCODE -157:

select cast('1' as date)

So that difference seems to explain the different query results...

Chris26
Participant
0 Likes

I'm indeed running with different settings: date_format = 'DD-MM-YYYY' and date_order = 'DMY'. The result for cast('1' as date) then is '01-07-2016'.

If I change them back to the default, I get the same results as you.

Chris26
Participant
0 Likes

This also means that if i choose 10 as the value for TestData in the first row we would have seen the same behaviour (1-1-1000 vs 10-07-2016)