In my Java application, it needs to find out whether the underlying Sybase db is case-sensitive or case-insensitive at server start-up and config the property accordingly, is there any proper ways to do that?
If select if 'A' = 'a' then 0 else 1 endif returns 1, then the DB is case sensitive.
Case sensitivity is indicated by the Character Set & Sort Order of the server.
You can pull the sort order, and character set from master..syscurconfigs
select value from master..syscurconfigs where config = 132 #Gives you Sort Order ID
select value from master..syscurconfigs where config = #Gives you Character Set ID
Once you have the two values, you can pull the name of the sort order:
select name from master..syscharsets where id = SortOrderID and csid = CharSetID
If the name includes nocase (for English sets), or nocs (non-English sets) then it is case insensitive.
*I know I am missing a value in my second query, but I will fill it in when I get back to my notes tomorrow
Related
I'm trying to update a table in SQL Server 2012 Management Studio. Rather than writing four separate Update statements, I'm attempting to see if it is possible to write one query that will update the same table for one column in four different ways depending on what the value of a column stores.
Assume I have a table called table_food with the following structure
|Customer|Preference|
+--------+----------+
|John |McDs |
|Div |KFC |
|Paul |KFC |
|Pablo |Wasabi |
My idea is to update the Preference column to new values and the query I had written was:
UPDATE table_food
SET Preference =
CASE WHEN Preference = 'McDs' Then 'Burger'
WHEN Preference = 'KFC' Then 'KingsMeal'
END
Now on my actual table, there are only 8 different options selected for preference and I just need two update 4. (I've just done two as an example above but I have four when statements...so just another two lines)
When I run the query it shows far more rows being affected and checking the results after I notice now there's only one option shown "Burger" with a count of 8 and all the other rows have been set to null. Is there something I'm missing?
That query will update every row on your table since it lacks a WHERE clause. And a CASE WHEN expression returns NULL if none of the WHEN conditions are true. You might want a query like:
UPDATE table_food
SET Preference =
CASE WHEN Preference = 'McDs' Then 'Burger'
WHEN Preference = 'KFC' Then 'KingsMeal'
END
WHERE Preference in ('McDs','KFC')
add else on your case statement.
UPDATE table_food
SET Preference =
CASE WHEN Preference = 'McDs' Then 'Burger'
WHEN Preference = 'KFC' Then 'KingsMeal'
ELSE Preference
END
or if you only want to update affected rows, you do update from
UPDATE table_food
SET Preference = t2.newPreference
FROM
(SELECT CASE WHEN Preference = 'McDs' Then 'Burger'
WHEN Preference = 'KFC' Then 'KingsMeal'
WHEN Preference = 'KFC1' Then 'KingsMeal1'
WHEN Preference = 'KFC'2 Then 'KingsMeal2'
END as newPreference, Preference
FROM table_food) t2
WHERE t2.Preference = table_food.Preference and coalesce(t2.newPreference, '') != ''
I recently had a request come through to remove some Agent names from the guest surname field in a client's database.
Eg. 'John Smith -Wotif'
When testing using the following UPDATE statement, the entire field was wiped rather than just the specific string.
UPDATE GUEST
SET SURNAME = REPLACE(' -Wotif',' -Wotif','')
WHERE SURNAME LIKE '% -Wotif'
I've since found that simply using the column name as the matching string will allow the full statement to work (even if already specified in the SET section), but I can't work out where the logic of the original statement effectively says 'wipe these fields entirely'.
Unless specified otherwise, surely the '' replacement only applies to the value contained within the substring, regardless of whether the string and substring match?
The first argument in the REPLACE function is the full string that you want to search. So you should be referencing the SURNAME field rather than specifying part of the string.
REPLACE(SURNAME,' -Wotif','')
You update SQL command should be like this -
UPDATE GUEST
SET SURNAME = REPLACE(SURNAME, 'FindValue' , 'ReplaceWithValue')
WHERE SURNAME LIKE '% -Wotif'
If you want to find & replace '-Wotif' with blank, then update command should be like below-
UPDATE GUEST
SET SURNAME = REPLACE(SURNAME, '-Wotif' , '')
WHERE SURNAME LIKE '% -Wotif'
I have an nvarchar field in my database called CatCustom which contains comma-separated 5-character codes. It can contain as little as one code, or as many as 20 codes, separated by commas.
Right now, I use this query to add a new 5-character code to the field in given records (in this case the new code is LRR01):
UPDATE dbo.Sources
SET CatCustom = CONCAT_WS(', ', RTRIM(CatCustom), 'LRR01')
WHERE SourceID IN (1,2,3,4,5,8,9,44,63,45,101,102,222,344)
I need to add to this though: I need the record to be updated only if that 5-character code doesn't already exist somewhere in the CatCustom field, to ensure that code is not in there more than once.
How would I accomplish this?
EDIT: I really don't understand how this can be considered a duplicate of the suggested thread. This is a VERY specific case and has nothing to do with creating stored procedures and or variables. The alleged duplicated thread does not really help me - sorry.
Use STRING_SPLIT function to split the comma separated list and then add Not Exist condition in the WHERE clause like below
UPDATE dbo.Sources
SET CatCustom = CONCAT_WS(', ', RTRIM(CatCustom), 'LRR01')
WHERE SourceID IN (1,2,3,4,5,8,9,44,63,45,101,102,222,344)
AND NOT EXISTS (SELECT 1 FROM STRING_SPLIT(CatCustom, ',') where value = 'LRR01')
UPDATE dbo.Sources
SET
CatCustom = CONCAT_WS(', ', RTRIM(CatCustom), 'LRR01')
WHERE
SourceID IN (1,2,3,4,5,8,9,44,63,45,101,102,222,344)
AND CatCustom NOT LIKE '%LRR01%';
I need some help from a MS SQL Master...
Short version:
When I execute a Conditional Where followed by a Contains, my query delays 1 minute (In its normal execution, it takes 200 milliseconds).
With this query, everything works fine:
Where
Contains(table.product_name, #search_word)
But with a Conditional Where, it takes 1 minute to execute:
Where
(#ExecuteWhereStatement = 0 Or (Contains(table.product_name, #search_word))
Long Version:
I'm using a stored procedure that receives some parameters. This Stored Procedure query a really large table, but everything is indexed properly and the query goes very well so far.
The main query is a little big, so I want to make the WHERE clause more smart possible, to avoid repeat multiple times the same statement.
The whole idea of the DataBase, is a history of purchases made by the State. So this query involves 3 tables:
Table 1 (table_purchase) - The purchase itself
id_purchase int (PK)
date_purchase datetime
buyer_code int (Nullable)
Table 2 (table_purchase_product) - The Items of a Purchase
id_product int (PK)
id_purchase int (FK of table_purchase)
product_quantity int (Nullable)
product_name varchar(255) (Nullable) (Full-Text-Indexed)
product_description varchar(2000) (Nullable) (Full-Text-Indexed)
id_product_bid_winner int (FK of table_product_bid)
Table 3 (table_product_bids) - The Bids for Each product of a Purchase
id_product_bid int (PK)
id_product int (FK of table_purchase_product)
product_brand varchar(255) (Nullable) (Full-Text-Indexed)
bid_value decimal (20,6)
So basicly, We have a "Purchase", that has several "Products (or Items)", and each "Product" has some "Bids (or Prices)"
And there is the Bad Girl (The SQL Stored Procedure):
ALTER PROCEDURE [dbo].[procPesquisaFullText]
#search_date datetime,
#search_word varchar(8000),
#search_brand varchar(255),
#only_one_bid bit = 0,
#search_buyer_code int = 0,
#quantityFrom decimal(20,6) = 0,
#quantityTo decimal(20,6) = 0
AS
BEGIN
SET NOCOUNT ON;
Declare #ExecuteWordSearch AS bit;
if (#uasg != 0 And #search_word = '')
begin
Set #ExecuteWordSearch = 0;
Set #search_word = 'nothing';
end
else
begin
Set #ExecuteWordSearch = 1;
end
Declare #ExecuteBrandSearch AS bit;
if (#search_brand = '')
begin
Set #ExecuteBrandSearch = 0;
Set #search_brand = 'nothing';
end
else
begin
Set #ExecuteMarcaSearch = 1;
end
begin
SELECT
pp.id_product,
pp.id_purchase,
pp.description
FROM
table_purchase_product pp
inner join table_purchase p on p.id_purchase = pp.id_purchase
WHERE
(p.date_purchase >= #search_date)
and (#search_buyer_code = 0 or (l.buyer_code = #search_buyer_code))
and (#quantityFrom = 0 or (li.product_quantity >= #QuantityFrom))
and (#quantityTo = 0 or (li.product_quantity <= #QuantityTo))
and (contains(pp.product_description, #search_word) or contains(pp.product_name, #search_word))
and (#only_one_bid = 0
or ((Select COUNT(*) From table_product_bid Where table_product_bid.id_product = pp.id_product) = 1))
and (#ExecuteBrandSearch = 0 Or (exists(
select 1
from table_product_bid ppb
where ppb.id_product_bid = pp.id_product_bid_winner
and contains(ppb.product_brand, #search_brand)
)
))
ORDER BY p.date_purchase DESC
end
END
So far, so good...
In the beginning I set two variables, used inside the query.
The first, verify if the user specified a "Buyer Code" AND didn't specify a "Search Word" (So, not the Product's description nor the Product's name is verified)
The second, verify if the user specified a "Specific Brand". If so, then the Winning Bid's BRAND is verified to match the users one.
Observation: You'll notice that when the "Search Words" is empty, I set them to "nothing". I do it because if the search term in the Contains is empty, it throws me a exception, even when it's not executed (I tested it in another query, absolutely isolated too)
As You can see, my user is able to search for:
- "Products" of Some Distinct Buyer "Purchase" (passing the #search_buyer_code parameter)
- A "Product" that contains a distinct word in its name or description
- A "Product" that has the Winner Bid of a specific Brand
- A "Product" that has only 1 bid at all
- A "Product" with a maximum and minimum quantity
And You'll notice that I used a lot of Conditions INSIDE the Where, producing a very dynamic Where, instead of using a "BIG If Else" statement, and repeating a lot of code. (I guess some "Googlers" will land here looking for Conditionally Wheres, and If so, I'm glad to help!)
Ok, so everything works veeery great at all. The query executes flawless. But here is the strange, damn, tricky issue:
If I want the user to be able to specify only a "Buyer Code" for Purchase, but No Word to Search of the Product using the code above (which is the first piece of code in the stored procedure does):
Changing from:
and (contains(pp.product_description, #search_word) or contains(pp.product_name, #search_word))
To:
and (#ExecuteWordSearch = 0 Or (contains(pp.product_description, #search_word) or contains(pp.product_name, #search_word)))
The query delays near 1 minute! (the execution is about 200 milliseconds for the query above).
But WHY??? I Use the same Logic of in all "Conditionally Wheres". I also use the same logic of having a flag/variable to indicate when execute the Where clause in the Word Search and the Brand Search, but the Brand Search works PERFECTLY! So Why, WHY only when I use the condition followed by a Contains my query delays 1 minute????
And this issue is not related with the amount of data, because I tried removing the entire Contains condition, allowing a lot of data to return, and it takes 1 second maximum...
Ow, It's a Microsoft SQL Server 2008 R2.
Thanks already for You read so far!
I cannot find the documentation I had around a very similar issue, but it sounded so familiar, I at least wanted to share what I remembered. Part of the issue is that for Sql Server, the full-text search engine is separate from the regular query execution engine, and so when you mix the two, in some cases, performance can tank. This is particularly true when the condition is an 'OR' rather than and 'AND'. (I remember hitting this exact situation). Conditional ANDs worked fine. But for OR, it's as if each condition gets evaluated repeatedly row by row.
Among the workarounds, one is, as already suggested, create your sql dynamically before execution.
Another would be to break the full-text and non-full text conditions into two search functions (literally UDF's) and then do whatever is needed (INTERSECT, EXCEPT, etc) with the two resultsets.
Try changing your WHERE clause to use a CASE statement, e.g.:
WHERE
CASE
WHEN #ExecuteWhereStatement = 0 THEN 1
WHEN #ExecuteWhereStatement = 1 THEN
CASE
WHEN CONTAINS([table].product_name, #search_word) THEN 1
ELSE 0
END
END = 1;
I have an entity framework query that has this at the heart of it:
SELECT 1 AS dummy
FROM [dbo].[WidgetOrder] AS widgets
WHERE widgets.[SomeOtherOrderId] = N'SOME VALUE HERE'
The execution plan for this chooses an index that is a composite of three columns. This takes 10 to 12 seconds.
However, there is an index that is just [SomeOtherOrderId] with a few other columns in the "include". That is the index that should be used. And when I run the following queries it is used:
SELECT 1 AS dummy
FROM [dbo].[WidgetOrder] AS widgets
WHERE widgets.[SomeOtherOrderId] = CAST(N'SOME VALUE HERE' AS VARCHAR(200))
SELECT 1 AS dummy
FROM [dbo].[WidgetOrder] AS widgets
WHERE widgets.[SomeOtherOrderId] = 'SOME VALUE HERE'
This returns instantly. And it uses the index that is just SomeOtherOrderId
So, my problem is that I can't really change how Entity Framework makes the query.
Is there something I can do from an indexing point of view that could cause the correct index to be selected?
As far as I know, since version 4.0, EF doesn't generate unicode parameters for non-unicode columns. But you can always force non-unicode parameters by DbFunctions.AsNonUnicode (prior to EF6, DbFunctions is EntityFunctions):
from o in db.WidgetOrder
where o.SomeOtherOrderId == DbFunctions.AsNonUnicode(param)
select o
Try something like ....
SELECT 1 AS dummy
FROM [dbo].[WidgetOrder] AS widgets WITH (INDEX(Target_Index_Name))
WHERE widgets.[SomeOtherOrderId] = N'SOME VALUE HERE'
This query hint sql server explicitly what index to use to get resutls.