-2

I have a simple SQL statement query that is executed as command from C# code. It is targetting DB2. I created variables for the server/schemas as follows. It throws error.

private const string DB2Query
            = @"SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";

I get this error.

ERROR [37000] [IBM][CLI Driver] CLI0118E Invalid SQL syntax. SQLSTATE=37000

However, I don't get that error when executing from SQL as follows:

SELECT Name as Name 
FROM MyServer..FOR3.Application 
WHERE ID = 'MOM'

To support this, I tried to also do something like below in code, still throws different error.

 private const string DB2Query
                    = @"SELECT Name as Name FROM {ServerName}..{Schema}.Application WHERE ID = ?";

It throws error on this line of code:

DataApplicationBlockHelper<string>.Get(db, dbCommand, Obj);

UPDATE

I found the culprit. It's not replacing the {Schema} placeholder. When I actually removed that from query and placed the schema name, it worked like a charm. It's a .net thing I believe? Can someone please help how to replace {Schema} with a value fetched from web.config?

HoneyBadger
  • 14,750
  • 3
  • 34
  • 48
Jasmine
  • 5,186
  • 16
  • 62
  • 114
  • 2
    If this is for IBM `DB2` - why did you add a `sql-server` tag to this?!?!? – marc_s Jan 14 '19 at 05:08
  • @marc_s: Some folks like you might be an expert of all :) Or at least would have encountered similar, for example, I am a MS folk and I now had to work with D2 too :( Thats why I added to hint those guys if they are aware :) – Jasmine Jan 14 '19 at 05:14
  • @marc_s: You helped me last time and ONLY you in the whole world ticked that point of SQL Server version where 2005 doesn't support table valued constructor and my group insert failed while individual insert passed. Nobody could think of that and all were only blaming me. Only you asked for version and compatibility and I compared with my personal laptop whjere it worked and my office it didn't work and when i post version difference some folk told its not supported. Anywya its not related to this question :) – Jasmine Jan 14 '19 at 05:19
  • @marc_s: I found the culprint. It's not replace the {Schema}. When I actually removed that from query and placed the Scnema name, it worked like charm. Its a .net thing I believe? Can you pls help on how to replace "{Schema}" with a va;ue fetched from web.config? – Jasmine Jan 14 '19 at 05:31
  • I know nothing about DB2 - but I believe the whole "schema" concept is quite *specific* to SQL Server, so I don't think you can just "replace" the `schema` placeholder with something from web.config and run that on DB2 - you most likely just need **different** SQL statements for DB2 than you can use against SQL Server. – marc_s Jan 14 '19 at 05:42
  • @marc_s: Why would my Replace function doesn't replace it? I do that in constructor. When I look at the query, it still says {Schema} and I don't see a good reason. Its way before we hit the DB2. Right? I maybe wrong, but curious to know. I am new to programming. Also, I suspect using the constant value starting with escape ignore "@" ? – Jasmine Jan 14 '19 at 05:45
  • @marc_s: WhatI am curious is plain string replacement doesn't replace. Why? – Jasmine Jan 14 '19 at 05:47
  • Even if you replace `{schema}` with an empty string, you still have a dot `.` between `{schema}` and `Application` in your SQL query which for DB2 probably shouldn't be there – marc_s Jan 14 '19 at 05:47
  • @marc_s: No, its a schema name. this.noSql = noSqlDefinition.Replace("{Schema}", this.DBSchema); – Jasmine Jan 14 '19 at 05:48
  • Its what I am doing. But it doesn't replace the {Schema} with my Schema name I fetched from the web.config. I do it in constructor – Jasmine Jan 14 '19 at 05:48
  • OK, but as I said: most likely DB2 doesn't **know** about schema....... that's SQL Server specific.ö... – marc_s Jan 14 '19 at 05:48
  • @marc_s: No, it works perfectly fine in DB2 visualiser. In fact, all my codes are using this format. Dont know whats wrong. When I replace the proper schema name in place of {Schema} it works perfectly fine. Something wrong in replacement as I saw in one blog https://github.com/lionheart/django-pyodbc/issues/123 – Jasmine Jan 14 '19 at 05:52
  • if you're using C# 6 you can use $ sign instead of @ sign on the strings (which will make your current string work). see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated – iSR5 Jan 14 '19 at 06:00
  • @iSR5: lol how would i know I use C#6? – Jasmine Jan 14 '19 at 12:40
  • @Learner if you using .NET 4.6 then you're using C#6. You also need to use VS 2015 or higher to get the full support. – iSR5 Jan 14 '19 at 13:02
  • @Learner a good explanation here https://stackoverflow.com/questions/19532942/which-version-of-c-sharp-am-i-using – iSR5 Jan 14 '19 at 13:03

1 Answers1

1

While I can't really speak to the syntax of DB2 queries themselves, so I'll rely on your assertion that the query itself should work...

What you have in C# is simply a string and nothing more:

private const string DB2Query = @"SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";

Note that there's no need for the @ operator in this string definition, so let's simplify:

private const string DB2Query = "SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";

While this string appears intuitively to have a placeholder that can be replaced with a value, if there's no code which does that anywhere then it won't happen. For that you have a few options. For example, you can use a placeholder that string.Format() understands:

private const string DB2Query = "SELECT Name as Name FROM {0}.Application WHERE ID = ?";

And then later in a method somewhere, when you want to use that string, apply the format value to it:

var sql = string.Format(DB2Query, someVariable);

In this case someVariable (which doesn't even need to be a variable and could be a string literal) would be used to replace the placeholder in the string.


Or, if you want to keep the named placeholder, you can potentially replace it manually:

private const string DB2Query = "SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";

and later in a method:

var sql = DB2Query.Replace("{Schema}", someVariable);

This would observably accomplish the same thing, perhaps with an extremely minor performance difference.


You could also take advantage of both approaches by using the more recent language feature of string interpolation. This would use the $ operator to apply format placeholders in place directly. I don't think you can use this in a const, it's more for a local variable. Something like this:

var sql = $"SELECT Name as Name FROM {someVariable}.Application WHERE ID = ?";

This would still perform the same replacement, putting someVariable where the placeholder is, it's just using a more concise syntax than a call to string.Format(). One thing to note about this syntax is that it makes it look more like this interpolation is happening directly in-place on the string. It's still a multi-step process behind the scenes, which is why it likely won't work on a const or on class members at all (and should I imagine produce a compiler error).

Remember that strings are immutable, so any operation you perform which modifies a string would be returning a new string rather than modifying the existing one in place.


In any case, you'll of course also need to apply your query parameter for the ? placeholder. Note that what C# considers to be a placeholder in a string formatting/interpolating operation and what DB2 considers to be a placeholder for a query parameter are two entirely different things which happen at different times in different environments. (One in the .NET runtime, one in the database server's query execution.) But again, I'm relying on your assertion that the database query itself works and the only problem we're focusing on here is the C# string placeholder.

David
  • 208,112
  • 36
  • 198
  • 279
  • David, thank you so much for the detailed response. Query works perfectly fine. Now, I was already using your 2nd approach using Replace function. My project is of old codes and they already have same ditto code as you wrote. However, that doesn't work (Perhaps it might work for prod environment?) Coz they set up the DB environment as Prod for those variables. Now, for Dev DB2 connections, perhaps it might not work due to different configuration setting possibly in DB2 for Dev and Prod? I don't know. – Jasmine Jan 14 '19 at 12:48
  • Well I can only try your 1st approach tomorrow morning as soon as I reach office. Its 11.48 PM night :) Thank you so much, its very insightful. And tune in to receive a response from me ;) – Jasmine Jan 14 '19 at 12:48
  • @Learner: *"I was already using your 2nd approach using Replace function"* - And did this not work in some way? If not, you'll want to specify what you tried and how it isn't working as expected in the question. *"perhaps it might not work due to different configuration setting possibly in DB2 for Dev and Prod?"* - Define "might not work", what specifically is failing? If something in DB2 is failing then that's outside the scope of your stated question, as your question asserts that the DB2 query works as expected. If you're asking about C# string formatting, that has nothing to do with DB2. – David Jan 14 '19 at 13:03
  • I realize that, I have placed two statements of Replace of which one is Schema and another one is server while actually I didn't specify any server in the query as I deleted the server placeholder from the query but didnt remember to remove the replace one for that. But why the heck it would throw error? I would assume ONLY if there are some string need to be replace, find it and if so replace, else ignore and go. Why the heck it throw irrelvant errors. Shit, wasted my half day – Jasmine Jan 14 '19 at 13:24
  • I remoted to my office even though its 12.20 AM midnight. Anyway, its sorted. I can sleep peacefully. Thank you so much for your help. – Jasmine Jan 14 '19 at 13:24