DB2 -- How to use LTRIM scalar function with 2 arguments? - database

I am new to DB2 (using version 10.1) and I'm trying to execute a simple ltrim function in a test query.
select ltrim(',1,2,3,4', ',') from sysibm.sysdummy1;
This results in the following error:
DB2 SQL Error: SQLCODE=-440, SQLSTATE=42884, SQLERRMC=LTRIM;FUNCTION, DRIVER=3.65.77
Based on the documentation here, it seems my example should work. Note, I can use the alternative trim function or the 1-arg version of ltrim:
select trim(l ',' from ',1,2,3,4') from sysibm.sysdummy1;
select ltrim(' test') from sysibm.sysdummy1;
And those works fine!
Are there some fundamental differences between the 2-arg form of ltrim and the other examples I provided?

This function was added in DB2 10.1 fix pack 2 -- you may want to upgrade.

Making some guesses here, but are you sure you're on 10.1? That version of that function you're trying to use appears to have been added in 10, so if you're on 9.x, it won't work.
If you are, you might check and see if your schema path includes SYSIBM:
SELECT CURRENT_PATH FROM SYSIBM.SYSDUMMY1
The "old" one-argument version of the function is in SYSFUN, which (if your path doesn't include SYSIBM) might be why you're still able to use that version.
If SYSIBM isn't in your path, you can try changing it using:
SET PATH = SYSIBM, CURRENT_PATH

Why not try STRIP() instead:
VALUES STRIP(',1,2,3,4', L, ',');
(side note: It is simpler to use the VALUES statement, rather than SELECT FROM SYSIBM.SYSDUMMY1)

Related

Django model based on an SQL table-valued function using MyModel.objects.raw()

If it's relevant I'm using Django with Django Rest Framework, django-mssql-backend and pyodbc
I am building some read only models of a legacy database using fairly complex queries and Django's MyModel.objects.raw() functionality. Initially I was executing the query as a Select query which was working well, however I received a request to try and do the same thing but with a table-valued function from within the database.
Executing this:
MyModel.objects.raw(select * from dbo.f_mytablefunction)
Gives the error: Invalid object name 'myapp_mymodel'.
Looking deeper into the local variables at time of error it looks like this SQL is generated:
'SELECT [myapp_mymodel].[Field1], '
'[myapp_mymodel].[Field2] FROM '
'[myapp_mymodel] WHERE '
'[myapp_mymodel].[Field1] = %s'
The model itself is mapped properly to the query as executing the equivalent:
MyModel.objects.raw(select * from dbo.mytable)
Returns data as expected, and dbo.f_mytablefunction is defined as:
CREATE FUNCTION dbo.f_mytablefunction
(
#param1 = NULL etc etc
)
RETURNS TABLE
AS
RETURN
(
SELECT
field1, field2 etc etc
FROM
dbo.mytable
)
If anyone has any explanation as to why these two modes of operation are treated substantially differently then I would be very pleased to find out.
Guess you've figured this out by now (see docs):
MyModel.objects.raw('select * from dbo.f_mytablefunction(%s)', [1])
If you'd like to map your table valued function to a model, this gist has a quite thorough approach, though no license is mentioned.
Once you've pointed your model 'objects' to the new TableFunctionManager and added the 'function_args' OrderedDict (see tests in gist), you can query it as follows:
MyModel.objects.all().table_function(param1=1)
For anyone wondering about use cases for table valued functions, try searching for 'your_db_vendor tvf'.

How to add a parameter to an existing stored procedure in SQL Server

I want to add a new parameter to an existing stored procedure. Body of this procedure may have been already customized by users so I can't drop and recreate it. I don't need to modify the body, just the signature.
So I thought to do a replacement of the last existing parameter by itself + the new parameter.
replace(OBJECT_DEFINITION (OBJECT_ID(id)),'#last_param varchar(max)=null','#last_param varchar(max)=null, #new_param varchar(max)=null')
It works fine if the following string is found
#last_param varchar(max)=null
but doesn't work if there is spaces in the string.
I would like to use a regex to be sure it works in all cases but I'm not sure it's possible in SQL Server.
Can you help me please ?
Thanks
SQL Server does not natively support regular expressions. You'll have to look at more manual string-analyzing with the available string functions. Something like this:
set #obDef = OBJECT_DEFINITION(OBJECT_ID(id))
set #startLastParam = PATINDEX('%#last_param%varchar%(%max%)%=%null%', #obDef)
if #startLastParam = 0 begin
-- handle lastParam not found
end else begin
set #endLastParam = CHARINDEX('null', #obDef, #startLastParam) + 4 -- 4 = len('null')
set #newDef = STUFF(#obDef, #endLastParam, 0, ', #new_param varchar(max)=null')
end
This isn't very fool-proof/safe though. PATINDEX() only gives you the same % wildcard you know from LIKE, it may match no character, it may match half the stored proc to find the word max somewhere entirely outside the signature.
So don't just run this in your customers production ;) but if you are certain about the current stored proc signature, this might just do the trick for you.

find exact string match and replace it in sql server

Is there a (supposedly) simple way to get an exact match when using the replace function in SQL Server 2012? (I'm open to other searching possibilities as well, of course)
For example, I'm using the following code to grab all the objects in a DB containing 'texter' in it at some point:
select OBJECT_NAME(object_id) name,
OBJECT_DEFINITION(object_id) code,
type
into #tester
from sys.objects
where OBJECT_DEFINITION(object_id) LIKE '%texter%'
This doesn't seem to differentiate between .texter, #texter or stupidtexter.
and so if I use:
update #tester
set code = REPLACE(code, 'texter', 'bluenose')
where code LIKE '%texter%'
It's going to replace any variant of 'texter' with 'bluenose'
Let's assume I only want to replace the ' texter' and '.texter' versions of this and nothing else (noting that within each object it is possible that #texter or stupidtexter may also be present in the object code).
Is there a way I can differentiate between the variants of 'texter', #texter and stupidtexter?
Thanks
The solution was:
replace(REPLACE(code, '.texter', 'bluenose'), ' texter', 'bluenose')
Thanks to Sean Lange for the answer!

Dapper parameters not working?

Dapper 1.34 (on earlier Dapper ver like 1.1x this worked fine).
db.Query(#"Select [whatever] from #TableName Where [PREFIX]='#Prefix' order by [something] desc",
new { TableName = tableName, Prefix = prefix })
Error: System.Data.SqlClient.SqlException (0x80131904): Must declare the table variable "#TableName".
I get same error trying to define DynamicParameters and passing those.
=======
I am currently doing string substitution {%1} .. but that does not seem acceptable ...
Can I please get a sample, also looking at test class for dapper I cant see it running, maybe something wrong with my project setup ?
No, that has never worked fine, due to how SQL works:
table names cannot be parameterized, and dapper has never offered this; that could work if you pass in a DataTable as a table-valued-parameter, though - which dapper does support - but I don't think this is what you are after
'#Prefix' is a string literal; you just mean #Prefix (no single quotes)

PostgreSQL query within PostGIS function

I am trying to run the following PostGIS query:
select ST_distance_spheroid(
ST_GeomFromText('POINT(
(select AsText(location) from test where name="EGMC")
)', 4326),
ST_GeomFromText('POINT(
(select AsText(location) from test where name="EGDY")
)', 4326),
'SPHEROID["WGS_1984",6378137,298.257223563]'
);
but keep getting an error:
ERROR: parse error - invalid geometry
HINT: "POINT(
(s" <-- parse error at position 9 within geometry
I'm happy that I know what the error means, I just don't know how to go about achieving what I want to do. I don't want to manually specify the location, it's stored in the database! I know the name of the place, so I want to get it's location by looking it up. How should I be doing this? Also, it seems a bit unnecessary to convert to a string to convert back, what else can I do?
If I can do this without having to specify variables that would be great.
Thanks.
You are mixing SQL and WKT, which are not the same. Furthermore, you don't need to recreate geometries that already exist. Query the existing geometries instead:
select ST_distance_spheroid(g1.location, g2.location, 'SPHEROID["WGS_1984",6378137,298.257223563]')
from test g1, test g2
where g1.name = "EGMC" and g2.name = "EGDY";

Resources