SQL sort order using 'ORDER BY CASE...' - sql

I'm trying to create a sorting function in SQL but I cannot make this thing work. I have really tried to find some similar problem on Stackoverflow but non that seems to solve my problem. I really not an expert on this things so hope that my explanation is understandable.
So case is as follows: I will list out products an on the website I have links for the user to click that decides what will be sorted, ProductName, ProductID and so on. Chosen sort type is collected from a request.querystring and I use CreateParameter to avoid the risk of SQL injections.
Here is the (simplified) SQL:
"SELECT * FROM Product" & _
"ORDER BY CASE ? " & _
"WHEN 'ID' THEN ProductID " & _
"WHEN 'IDART' THEN ArticleNumber " & _
"ELSE ProductName " & _
"END DESC"
objConnProdList.CommandType = 1
SET objParam = objConnProdList.CreateParameter("#strOrder", adVarchar, adParamInput, 10, "%" & request.querystring("OrderBy") & "%")
Using ELSE I will get the error message:
Conversion failed when converting the nvarchar value 'DiningChair' to data type int.

The problem is that you can't mix different data types in a single case. The syntax would be ok if you convert the values to nvarchars, but that doesn't sort them properly.
If you're using dynamic SQL like in the example, just add the lines to order by you actually need. If you have a stored procedure or something like that, it works with separate order by clauses like this:
SELECT * FROM Product
ORDER BY
CASE #xxx WHEN 'ID' then ProductID end,
case #xxx WHEN 'IDART' THEN ArticleNumber end,
ProductName DESC

i think you make it overly complicated.
var sql = "SELECT * FROM Product";
switch (strOrder)
case when "ID":
sql = sql & " ORDER BY ProductID"
break;
case when "IDART":
sql = sql & " ORDER BY ArticleID"
break;
end;
and run it. there is no place for injection as there is no variable you inject.

This is a variation on JamesZ's answer:
with const as (
select ? as xxx
)
SELECT *
FROM const cross join Product
ORDER BY (CASE xxx WHEN 'ID' then ProductID end),
(case xxx WHEN 'IDART' THEN ArticleNumber end),
ProductName DESC

Related

Use a parameter in SSRS for table_name

I have scoured the internet for options and the only one I have found that can do it is by using a $Proc however I am trying to avoid that.
I would think it would be pretty simple to use a parameter to select a different table depending on what the user chooses from a drop down.
Here it is:
- There are two tables the report needs to use,
* some_table_CY (current year table)
* some_table_STLY (same time last year table)
So I created a parameter that gives the user the option to select "Current_Year" or "Last_Year", depending on which one the user chooses the parameter would then be used in the select statement, something like this: "SELECT * FROM :pReportVersion"
However, it is not working. I need it to do this, not using a union since unioning these two tables causes HUGE performance issues and the query takes more than 4 hours to run which is not acceptable for a report that users need on request.
(This is querying oracle)
Use the Dataset expression and set it to:
="SELECT * FROM " & Parameters!ReportVersion.Value
For longer queries you may need to wrap each line with quotes, append with an ampersand and add a line feed:
="SELECT * " & VBCLRLF &
"FROM " & Parameters!ReportVersion.Value & VBCRLF &
"WHERE FIELD1 > 10 " & VBCRLF &
"AND FIELD2 = 'YES' "
you can still use the union..
Say you have a parameter called #year
set the available values to the following (specify values)
current year for label and 1 for value
last year for label and 2 for value
Then your dataset can be something like this:
select * from some_table_CY
where #year = 1
union all
select * from some_table_LY
where #year = 2

How to define variables in select statement vb.net?

I have a query like this
Dim view_src_14 As String = GetParameterValue("ViewSrc14")
Dim calendar_date_14 As String = GetParameterValue("CalendarDate14")
select calendar_date,view_src,sum(effective) effective_total, sum(ineffective) ineffective_total
from wrk_alert_effectiveness
where calendar_date='" + calendar_date_14 + "' and '" + view_src_14 + "'
group by 1,2
order by 1 desc;
calender_date_14 and view_src_14 are variables... when I run the query it bring this error:
invalid input syntax for type date: ""
Where do i make the changes??
I don't think this is specific enough for an answer, but it is too long for a comment.
You are trying to execute a SQL statement where you pass in values for constants in the statement. This is allowed and a part of SQL -- using parameters. There are two types of parameters, named parameters and positional parameters.
select calendar_date, view_src,
sum(effective) as effective_total, sum(ineffective) as ineffective_total
from wrk_alert_effectiveness
where calendar_date = #date1 and #date2
group by 1, 2
order by 1 desc;
Often, these are represented by ? for anonymous parameters. Sometimes named ones are introduced with colons.
The exact syntax depends on your database and the application interface you are using. My point is that you should learn about parameters and how to use them.
"select calendar_date, view_src, sum(effective) effective_total,
sum(ineffective) ineffective_total
from wrk_alert_effectiveness
where calendar_date= '" + #CalendarDate + "' AND " + #ViewSrc + "
group by 1,2
order by 1 desc;"

Data type missmatch in criteria expression

Is there any wrong in this SQL statement in VBA:
myConnection.Execute "update item_gallery set quantity = 'qtToTotal' where item = 'Desc' and gallery ='Gallery_Name'"
where
qtToTotal = qtTo + qtFrom
While Not myRecordSetItem.EOF
If !item_ID = myRecordSetItem.Fields("item_ID").Value Then
Desc = myRecordSetItem.Fields("Desc").Value
End If
myRecordSetItem.MoveNext
Wend
While Not myRecordSetGallery.EOF
If !To = myRecordSetGallery.Fields("Gallery_ID").Value Then
Gallery_Name = myRecordSetGallery.Fields("Gallery_Name").Value
End If
myRecordSetGallery.MoveNext
Wend
it always give me the message :
"data type missmatch in criteria expression"
This:
myConnection.Execute "update item_gallery set quantity = 'qtToTotal' where item = 'Desc' and gallery ='Gallery_Name'"
where
qtToTotal = qtTo + qtFrom
Looks like it should read more like this (but I'm not 100% as I have some questions to ask):
myConnection.Execute "UPDATE item_gallery" _
& " SET quantity = qtToTotal" _
& " WHERE item = Desc" _
& " AND gallery = Gallery_Name" _
& " AND qtToTotal = (qtTo + qtFrom)"
My guess is you're getting this error because you've surrounded what look like field names in single quotes ('), which is what you do when you're telling SQL that you're wanting a piece of text rather than one of the fields in your database.
Examples of when to use single quotes:
...when you want to refer to just a piece of text in a field formatted as text:
"SELECT * FROM tblNames WHERE FirstName = 'John'".
...when you want to refer to text that's currently in a field on an open form that is formatted as text:
"SELECT * FROM tblNames WHERE FirstName = '" & Me.txtFirstName & "'".
But in your case it looks like you want a field from the underlying tables, so you don't need any single quotes around the field name.
Your quantity field sounds like it could well be a numeric field and you've essentially asked it to try and put the piece of text "qtToTotal" in the quantity field, which it won't be able to do if that field is only setup to accept numbers.
A few questions though as I suspect there might be more problems here (and I'll update this based on your answers):
Are all these fields...
quantity
qtToTotal
item
Desc
gallery
qtToTotal
qtTo
qtFrom
...located in the table item_gallery?
If they're not then you need to create JOIN(s) in your SQL statement between the item_gallery table and whatever table(s) the other fields come from using a field that matches/relates the records from both tables.
What is the data type for each of these fields?
Where you've used an = between 2 fields, are both those fields the same data type? If not it will cause a mismatch.
Also: I'd advise against using "Desc" as a field name as DESC is a word reserved for "descending order" in an ORDER BY clause in SQL.

VB.NET 2010 & MS Access 2010 - Conversion from string "" to type 'Double' is not valid

I am new to VB.Net 2010. Here is my problem: I have a query that uses a combo box to fetch many items in tblKBA. All IDs in the MS Access database are integers. The combo box display member and value member is set to the asset and ID of tblProducts.
myQuery = "SELECT id, desc, solution FROM tblKBA WHERE tblKBA.product_id = '" + cmbProducts.SelectedValue + "'"
In addition to getting items from the KBA table, I want to fetch the department details from the department table, possibly done in the same query. I am trying to do it in two separate queries.
myQuery = "select telephone, desc, website from tblDepartments where tblDepartments.product_id = tblProducts.id and tblProducts.id = '" + cmbProducts.SelectedValue + "' "
All help will be appreciated!
Change the '+' to a '&' then the compiler would be happy.
try adding .toString to cmbproducts.selectedvalue or do "tblKBA.product_id.equals(" & cmbProducts.selectedValue.toString & ")"
1.) Don't use string concatenation to build your query. Use parameters.
2.) I am guessing that tblKBA.product_id is a double and not a string, so don't put quotes around it.
myQuery = "SELECT id, desc FROM tblKBA WHERE tblKBA.product_id = ?"
3 things. Test your value before building the select statement. Second, Use .SelectedItem.Value instead of .SelectedValue. Third, protect yourself from sql injection attack. Use parameters, or at the very least check for ' values.
If IsNumeric(cmbProducts.SelectedItem.Value) = False Then
'No valid value
Return
End If
myQuery = String.Format("SELECT id, desc FROM tblKBA WHERE tblKBA.product_id = {0}", cmbProducts.SelectedItem.Value.Replace("'", "''"))

SQL Server error '80040e14' Ambiguous column name

I have an admin page to search for products to edit, but the page keeps returning the error:
Microsoft OLE DB Provider for SQL Server error '80040e14' Ambiguous
column name 'prod_id'. /__admin/searchproducts.asp, line 89
I'm unsure why this error is cropping up, because the page and site is a direct copy of another website and associated MSSQL database and the search product page works on that site.
This is the code in question (not sure if it will be easy to read here though);
if request("fldSubmitted") <> "" then
if request("fldprodid") <> "" and isNumeric(request("fldprodid")) then
SQL = "select * from products where prod_id = " & cdbl(request("fldprodid"))
else
SQL = "select "
if request("showtop") <> "all" then
SQL = SQL & " top " & request("showtop") & " " & replace(replace(request("orderby")," asc","")," desc","") & ", "
end if
SQL = SQL & "prod_name, prod_id, prod_code, prod_icon, prod_thumb, prod_numViews, prod_archived"
if request("fldLabel") <> "" then SQL = SQl & ", label_name"
if request("fldCat") <> "" then SQL = SQL & ", cat_name"
if request("fldSubcat") <> "" then SQL = SQL & ", subcat_name"
SQL = SQL & " from products"
if request("fldLabel") <> "" then SQL = SQL & ", labels"
if request("fldCat") <> "" then SQL = SQL & ", categories"
if request("fldSubcat") <> "" then SQL = SQl & ", subcategories"
sql = sql & " where 1=1"
if request("fldLabel")<> "" then SQL = SQL & "and prod_label = label_id "
if request("fldCat") <> "" then SQL = SQL & "and prod_category = cat_id "
if request("fldSubcat") <> "" then SQL = SQL & "and prod_subcategory = subcat_id "
if request("fldName") <> "" then SQL = SQL & " and (prod_name like '%" & replace(request("fldName"),"'","''") & "%')"
if request("fldCode") <> "" then SQL = SQL & " and (prod_code like '%" & replace(request("fldCode"),"'","''") & "%')"
if request("fldLabel") <> "" then SQL = SQL & " and prod_label = " & request("fldLabel")
if request("fldCat") <> "" then SQL = SQL & " and prod_category = " & request("fldCat")
if request("fldSubcat") <> "" then SQL = SQL & " and prod_subcategory = " & request("fldSubcat")
if request("fldArchived") = "No" then
SQL = SQL & " and prod_archived = 0"
if request("instock") = "No" then SQL = SQL & " and prod_numleft > 0"
end if
SQL = SQL & " order by " & request("orderby")
end if
The problem is that the query will select the column prod_id, but more than one of the tables referenced has a column with that name.
The query returns results from more than one table, but exactly which table depends on the values of the various parameters. So, that might explain why it works in one circumstance but not another.
You can make the prod_id reference unambiguous by prefixing it with the table name, e.g.
myTable.prod_id
I presume it's fairly obvious (to you) which table is the right one (of course it has to be a table that's ALWAYS part of the query, not one that's only there under certain conditions).
In the second half of the query the you could possibly select from the tables products, labels, categories and subcategories. If any of these tables have a prod_id the DBMS won't know which one you are referring to. A simple revision is to alias each table, e.g products p, labels l, etc.
An even better refacotoring would be to alter the query to us joins:
SELECT p.prod_name, l.label_name
FROM products p
JOIN labels l
ON l.label_id = p.label_id
WHERE p.in_stock > 0
One other tip when dealing with these problems is to response.write the SQL string and copy it in to Management Studio instead, this will help you see passed the string manipulation to the error.
Finally, I would suggest looking at Stored Procedures so you can remove the SQL from your application.
Edit
Following on from some chat in the comments, if Stored Procedures are out of the question then a parameterized query would be a good step forward. This will bring a performance gain as the query plan will be cached and avoids the most basic forms of SQL Injection attack.
Are you sure that there is only one table with a column named prod_id in the list of tables that you're using in the query?
The code is a little difficult to read and work through but unless you can guarantee the same query runs in both the working and non-working scenarios then I would put it down to that.
This error is usually seen when you have more than one table or view in your query with the same column name and have not explicitly said which one you wanted to use. You should get in the habit of prefixing all columns with the table/view if there is going to be more than one to avoid ambiguity.
EDIT: in this example, obviously your products table has a prod_id but you'll probably be able to confirm that labels, categories or subcategories also has a prod_id column
Thank you for all of the replies. Sorry for not replying soon, but I haven't received any alerts to say that people had replied. Lol.
I seem to have fixed the error now. I removed 'prod_id' from the following line;
SQL = SQL & "prod_name, prod_id, prod_code, prod_icon, prod_thumb, prod_numViews, prod_archived"
Seems to work okay now. A little odd that the other site works with the exact same code, but all sorted now. :D
Once again, many thanks for the replies. Very much appreciated.