MS SQL statement using PARTIAL and DISTINCT in VB.NET - distinct

I have a table called Postcodes which has over half a million records.
Inside this table i have a column called PostCodeText which has the following:
NG1 1AA
NG1 1AB
NG1 1AC
NG2 1AA
NG2 5TH
NG17 3LP
DE15 4BP
NG17 5GL
DE19 4EE...
What I need is a MSSQL statement that return DISTINCT matches based on a partial string. For example: If I wanted to find all distinct NG postcodes I would want to return:
NG1
NG2
NG17
I've tried something like:
SELECT DISTINCT postcodetext
FROM postcodes
WHERE (postcode_text LIKE 'NG%')
ORDER BY postcodetext
I feel I might be close to the answer but its not there yet, any help would be much appricated.
Also I heard that using LIKE is a slower option then using = is there a faster way then doing this?

Try
SELECT LEFT(postcodetext,CHARINDEX(' ',postcodetext,0))
FROM postcodes
WHERE postcodetext like 'NG%'
GROUP BY LEFT(postcodetext,CHARINDEX(' ',postcodetext,0))
ORDER BY postcodetext
OK, I think I'm missing something here, the above statement work fine (if I drop the ORDER BY), when I run it in management studio. But when I run it in my VB.net code I'm having an issue:
After running the statement and assigning the values into my datatable, I then use the following code :
For Each rows In dt.Rows
Select Case opt
Case 1 '
frmSettings.lstAllPostcodes.Items.Add(rows.Item("postcodetext"))
frmSettings.ProgBarSettings.Value = i
i = i + 1
End Select
Next
It fails when trying to reference rows.item("postcodetext"). I realise that has something to do with the SELECT statement using the LEFT of. I would like my listbox to hold the partial results (ie NG1, NG2, NG17 etc etc)

Related

check multiple condition with like statement

I check two columns if the string "done" or "completed" is available in either of these columns.at this moment I write
case when col1 like '%done%'
or col1 like "%completed%'
or col2 like "%done%'
or col2 like "%completed%'
end as status
this is a sample so it's only 4 lines however if there are multiple strings that need to check it takes a lot of effort to write code like this. Can we write which gives a similar result?
(col1||"-"||col2) like (%done%,%completed%)
i know above code is not possible, but do we have any alternative?
If you have a lengthy list, create a table with one column and insert a row for each key word. Then write your query to join to this table using the LIKE operator:
SELECT DISTINCT m.*
FROM maintable m,
keyword_table k
WHERE m.col1 LIKE '%'||k.keyword||'%'
Just be aware that this will not perform well in bulk (millions of rows). That would require more advanced techniques, but for small tables this is fine.

Showing converted Base64 (from hex) in an existing SQL Server 2019 view

I do voluntary work at an animal shelter. We have an application which uses a SQL Server 2019 database. I have created a view that includes a varbinary(max) column. The value in this column is a picture, stored in hexadecimal-format. I would like to convert this Hex-value to a base64-binary file and add these to the view as an extra column.
I found the perfect solution for my situation in SQL Server : hex to base64. The example provided converts 1 single hex-value into 1 base64-value. I now need to add this solution to my view, but I'm not having any success.
The offered solution:
DECLARE #TestBinHex varchar(max), #TestBinary varbinary(max), #Statement nvarchar(max);
SELECT #TestBinHex = '0x012345';
SELECT #Statement = N'SELECT #binaryResult = ' + #TestBinHex;
EXECUTE sp_executesql #Statement, N'#binaryResult varbinary(max) OUTPUT', #binaryResult=#TestBinary OUTPUT;
SELECT
CAST(N'' AS XML).value(
'xs:base64Binary(xs:hexBinary(sql:column("bin")))'
, 'VARCHAR(MAX)'
) Base64Encoding
FROM
(SELECT #TestBinary AS bin) AS bin_sql_server_temp;
A simplified version of my view:
SELECT
a.cat_id, a.catname, s.cat_id,
s.stay_id, s.shelter_handler, s.shelter_kennel, s.picture
FROM
dbo.animal AS a
OUTER APPLY
(SELECT TOP 1 *
FROM dbo.shelterdata
WHERE a.cat_id = s.cat_id
ORDER BY s.stay_id DESC) AS S
WHERE
(a.cat_id IS NOT NULL) AND (s.leave_date IS NULL)
The view shows an overview of all cats currently present in the shelter (leave_date is NULL). The reason for the TOP 1 is that sometimes shelter animals get returned, and the application then assigns a new stay_id. To prevent duplicate values from the join, I only return the value of the most recent stay_id.
What I am trying to achieve: the second table (dbo.shelterdata) includes the picture, stored in hex value. I'd like to add a column Base64Encoding to the view which includes the converted value.
My attempts
I was successful in replacing the static value '0x012345' by a SELECT statement. But the way the solution is formatted, it only allows for one input value. So I had to restrict it with a WHERE clause. It is obvious to me that I need to make a subquery which inputs the hex value based on the unique cat_id. However, it has been many years since I worked with variable, so I'm struggling with the formatting of the statement.
My request
Does anyone have a suggestion how to build the conversion into the view?
Any assistance would be greatly appreciated.
After searching for a few more hours, I stumbled onto the solution. Maybe it will help someone else in the future. The solution is remarkably simple, as is often the case.
My view, mentioned above, is called dbo.shelter_view
select sv.picture,sv.cat_id,
cast('' as xml).value(
'xs:base64Binary(sql:column("sv.picture"))', 'varchar(max)'
) as Base64Encoding
from dbo.shelter_view as SV

How to make a dynamic select based on a result set from previous step on Pentaho Kettle?

I want to execute a select statement based on a result set from a previous step, something like this:
select column from table where column in (previous step);
Basically this step (filter rows) will split a group of ids based on a condition. I want to make a select with those who tested false but i don't know how to select only those. The table in question, which I want to select, it's very big and it is very expensive to select all records and join with the result set, so I wish to select just the group that I need, is this even possible ?
https://i.stack.imgur.com/Xu1qt.png
Ok, let me try to be more specific.
Basically I Have 3 steps as my print shows.
First step is a table input, which I select from a table.
Second step is a database lookup, which I look on other table to get some fields that I want.
And third step it's a filter rows, where I kinda make a if else statement.
After my third step (filter rows) I have 2 streams: True or False.
Each stream returns me a group of ids and other fields too but it's not that important here, I guess.
I want to make a select statement based on those ids returned from previous step (Filter rows 3° step).
Basically the behaviour that I want its similar to this query:
select *
from table
where id in ("previous step");
Where table will always be the same table, so I don't think this will be a problem or something.
And "previous step" means all ids returned after the 3° step (filter rows).
What i am doing right now is: I have another table input on the other side which I make a merge join with this result set(from 3° step). But I have to make a select of the entire table and then, join with my result set, what is very expensive, and I'm wondering if i can get the same result, but with more performance.
I don't know if I am being clear enough, but I apologize right now because english it's not my main language, but I hope you guys can understand me now, thanks.
You can use three steps to achive this.
First, use a Memory group by step to group ids as a field.The aggregate tyoe should beConcatenate strings separated by ,
Second,use a User defined java expression step to generate a new field contains the SQL we need.The expression may like"SELECT id,created FROM test WHERE order_id IN ("+ ids +")" and ids is the group result from last step.
At last,we can use a Dynamic SQL row step to look up datas by the specified SQL.

How to identify column types during sql injection?

Situation is following:
I have identified sql injection attack vector, and have following information about target table:
It has six columns. (Identified using "order by").
I can see output of 3 of them (table is displayed). two seems kind of enum value (integer in database?), and one is a date. I have very strong suspicion that col #6 is date column.
I'm almost sure the database is oracle. (ROWNUM works and LIMIT gives error).
I don't have error messages (always generic text is returned - "something went wrong").
Frontend is PHP if that matters. But there might be middle layer between it and database (e.g. java service), so I'm not sure where the query is being constructed.
E.g. following search query works as expected:
test' AND ROWNUM <= 5 ORDER BY 6--
EDIT-FROM-HERE:
Ok after help from comments, following query works:
test' UNION ALL SELECT null,null,null,null,null,null FROM dual--
(I was missing FROM dual part. Thank you #kordirko very much!)
This query adds one empty record in the output table (it is visually visible), so I'm definitely on the right track!
Now following line also works:
test' UNION ALL SELECT null,null,null,n't',null,null FROM dual--
I correctly identified 4th column and now it displays uppercase(?) letter T where I expected it to appear. So far so good. But it gives error when I input any string longer than 1 char! So following gives an error:
test' UNION ALL SELECT null,null,null,n'test',null,null FROM dual--
I'm no expert in SQL injection, and especially ORACLE (though have experience with MsSql).
I think the problem is something unicode-ansi-whateverencoding-related. For other rows (selected by original query before my UNION ALL SELECT addition) the 4th column gives multi-character normal strings. But when I try to inject desired string, it only works if it's one character, and also misteriously displays it in uppercase. I think this must be some encoding problem. I just discovered I needed n prefix for unicode string after 1 hour of searching and struggling. Maybe some Oracle gurus can quickly spot what mistake do I have in my query?

Is it possible to return a list of numbers from a Sybase function?

I'm trying to overcome a very serious performance issue in which Sybase refuses to use the primary key index on a large table because one of the required fields is specified indirectly through another table - or, in other words;
SELECT ... FROM BIGTABLE WHERE KFIELD = 123
runs in ms but
SELECT ... FROM BIGTABLE, LTLTBL WHERE KFIELD = LTLTBL.LOOKUP
AND LTLTBL.UNIQUEID = 'STRINGREPOF123'
takes 30 - 40 seconds.
I've managed to work around this first problem by using a function that basically lets me do this;
SELECT ... FROM BIGTABLE WHERE KFIELD = MYFUNC('STRINGREPOF123')
which also runs in ms.
The problem, however, is that this approach only works when there is a single value returned by MYFUNCT but I have some cases where it may return 2 or 3 values.
I know that the SQL
SELECT ... FROM BIGTABLE WHERE KFIELD IN (123,456,789)
also returns in milliseconds so I'd like to have a function that returns a list of possible values rather than just a single one - is this possible?
Sadly the application is running on Sybase ASA 9. Yes I know it is old and is scheduled to be refreshed but there's nothing I can do about it now so I need logic that will work with this version of the DB.
What about using a temporary table to store your numbers? So your sql would look like this:
select kfield into #tmpKfield
from littleTable
where UNIQUEID = 'STRINGREPOF123'
select * from bigTable
where kfield in (select kfield from #tmpKfield)
go
drop table #tmpKfield
go
That is how I try to solve your issue.

Resources