Trying to execute an update query where rows are variables from TEdit - mysql

I have a table which has values that need to be updated. There are quite a few typos as different people have added items in the past, so I have to use 'like' despite everything.
I created a Form with all the necessary fields that need updating. I used simple TEdit and a TLabel. The plan is that one picks a type of item from an edit box and also use a TListBox.
Then one adds the information to be updated into each TEdit.
I create an update procedure as follows:
MyQuery1.SQL.Text := ' UPDATE TheTable SET iName = edtName.text WHERE iType like "%edtType.text%" ';
MyQuery1.SQL.Text := ' UPDATE TheTable SET iPart = edtPart.text WHERE iType like "%edtType.text%" ';
...
MyQuery.ExecSQL;
My problem is passing the edtVariables in the correct format. How does one add the "% before and %" after the edtVariable?
I tried '"%'+edtPart.text+'%"' and such like, but I've never had to do this at runtime before.

Using FireDAC in a parametrized query, you use ':' in front of a parameter name:
MyQuery1.SQL.Text := 'UPDATE TheTable SET iName = :NameText WHERE iType like :TheValue';
Then you set the parameter value before executing the request:
MyQuery1.ParamByName('TheValue').AsString := EdtType.Text;
MyQuery1.ParamByName('NameText').AsString := EdtName.Text;
MyQuery1.ExecSQL;

Related

I am not able to determine the proper syntax for a DBeaver MySQL statement [duplicate]

How to declare a variable in mysql, so that my second query can use it?
I would like to write something like:
SET start = 1;
SET finish = 10;
SELECT * FROM places WHERE place BETWEEN start AND finish;
There are mainly three types of variables in MySQL:
User-defined variables (prefixed with #):
You can access any user-defined variable without declaring it or
initializing it. If you refer to a variable that has not been
initialized, it has a value of NULL and a type of string.
SELECT #var_any_var_name
You can initialize a variable using SET or SELECT statement:
SET #start = 1, #finish = 10;
or
SELECT #start := 1, #finish := 10;
SELECT * FROM places WHERE place BETWEEN #start AND #finish;
User variables can be assigned a value from a limited set of data
types: integer, decimal, floating-point, binary or nonbinary string,
or NULL value.
User-defined variables are session-specific. That is, a user
variable defined by one client cannot be seen or used by other
clients.
They can be used in SELECT queries using Advanced MySQL user variable techniques.
Local Variables (no prefix) :
Local variables needs to be declared using DECLARE before
accessing it.
They can be used as local variables and the input parameters
inside a stored procedure:
DELIMITER //
CREATE PROCEDURE sp_test(var1 INT)
BEGIN
DECLARE start INT unsigned DEFAULT 1;
DECLARE finish INT unsigned DEFAULT 10;
SELECT var1, start, finish;
SELECT * FROM places WHERE place BETWEEN start AND finish;
END; //
DELIMITER ;
CALL sp_test(5);
If the DEFAULT clause is missing, the initial value is NULL.
The scope of a local variable is the BEGIN ... END block within
which it is declared.
Server System Variables (prefixed with ##):
The MySQL server maintains many system variables configured to a default value.
They can be of type GLOBAL, SESSION or BOTH.
Global variables affect the overall operation of the server whereas session variables affect its operation for individual client connections.
To see the current values used by a running server, use the SHOW VARIABLES statement or SELECT ##var_name.
SHOW VARIABLES LIKE '%wait_timeout%';
SELECT ##sort_buffer_size;
They can be set at server startup using options on the command line or in an option file.
Most of them can be changed dynamically while the server is running using SET GLOBAL or SET SESSION:
-- Syntax to Set value to a Global variable:
SET GLOBAL sort_buffer_size=1000000;
SET ##global.sort_buffer_size=1000000;
-- Syntax to Set value to a Session variable:
SET sort_buffer_size=1000000;
SET SESSION sort_buffer_size=1000000;
SET ##sort_buffer_size=1000000;
SET ##local.sort_buffer_size=10000;
SET
SET #var_name = value; /* or */ SET #var_name := value;
both operators = and := are accepted
SELECT
SELECT col1, #var_name := col2 from tb_name WHERE "condition";
if multiple record sets found only the last value in col2 is kept (override);
SELECT col1, col2 INTO #var_name, col3 FROM ...
in this case the result of Select is not containing col2 values
Ex both methods used
-- TRIGGER_BEFORE_INSERT --- setting a column value from calculations
...
SELECT count(*) INTO #NR FROM a_table WHERE a_condition;
SET NEW.ord_col = IFNULL( #NR, 0 ) + 1;
...
Use set or select
SET #counter := 100;
SELECT #variable_name := value;
example :
SELECT #price := MAX(product.price)
FROM product
Different types of variable:
local variables (which are not prefixed by #) are strongly typed and scoped to the stored program block in which they are declared. Note that, as documented under DECLARE Syntax:
DECLARE is permitted only inside a BEGIN ... END compound statement and must be at its start, before any other statements.
User variables (which are prefixed by #) are loosely typed and scoped to the session. Note that they neither need nor can be declared—just use them directly.
Therefore, if you are defining a stored program and actually do want a "local variable", you will need to drop the # character and ensure that your DECLARE statement is at the start of your program block. Otherwise, to use a "user variable", drop the DECLARE statement.
Furthermore, you will either need to surround your query in parentheses in order to execute it as a subquery:
SET #countTotal = (SELECT COUNT(*) FROM nGrams);
Or else, you could use SELECT ... INTO:
SELECT COUNT(*) INTO #countTotal FROM nGrams;
Declare:
SET #a = 1;
Usage:
INSERT INTO `t` (`c`) VALUES (#a);
For any person using #variable in concat_ws function to get concatenated values, don't forget to reinitialize it with empty value. Otherwise it can use old value for same session.
Set #Ids = '';
select
#Ids := concat_ws(',',#Ids,tbl.Id),
tbl.Col1,
...
from mytable tbl;
I would like to give my awnswer here so people can try, solution for MySql that i think is easyer to understand:
set #countVal = (select count(*) from STATION);
/**
499/2 = 249,5 -> 250 -- ceil
499/2 = 249,5 + 1 = 250,5 -- floor 250
500/2 = 250 -- ceil 250
= 250 + 1 = 251 -- flor 251
**/
set #ceilVal = ceil(#countVal/2);
set #floorVal = floor( (#countVal/2) + 1);
SELECT ROUND(AVG( latitude ),4) FROM
(SELECT #lineNum:= #lineNum + 1 as id,
lat_n as latitude
FROM STATION s, ( SELECT #lineNum :=0 ) pivot
ORDER BY lat_n) as a
WHERE id IN ( #ceilVal, #floorVal );
SET Value
declare #Regione int;
set #Regione=(select id from users
where id=1) ;
select #Regione ;

How can i pass multiple values to an array parameter function

i need your help.....how can i pass multi values into single parameter in a function?
The values 'AAA 1','BBB 2', 'CCC 3' 'DDD 4' are to be passed to the same parameter "v_type", the values will be sent based on the selection from the drop down in the front end screen. The user can select one or more values from the list and those values should be passed to the procedure which in turn will be passed to the WHERE clause of the SELECT statement inside the procedure.
My function is somenthing like this:
Example
CREATE OR REPLACE FUNCTION FN_GET_ROWS
(v_date_ini IN DATE,
v_date_end IN DATE,
v_type IN VARCHAR2
)
RETURN TEST_TABTYPE
AS
V_Test_Tabtype Test_TabType;
BEGIN
SELECT TEST_OBJ_TYPE(DATE, NAME, ALERT)
BULK COLLECT INTO V_Test_TabType
FROM (select date, name, alert
from Table
where DATE BETWEEN v_date_ini AND v_date_end
AND Alert in (select REGEXP_SUBSTR (v_type, '[^,]+', 1, level)
from dual
connect by level <= length(regexp_replace(v_type,'[^,]*'))+1)
);
RETURN V_Test_TabType;
END;
Searching internet i found that maybe an Varray works but i dont know how to assign it to the variable :type with the parameters that the user selects on the screen.
I create this types on database, how can i used it? i'm kind a new in plsql.
CREATE TYPE alert_obj AS OBJECT (type_alert VARCHAR2(60));
CREATE TYPE alert_varray_typ AS VARRAY(100) OF alert_obj;
Thanks for your help
Emanuel.
I dont know, if I really understand your problem. But I think, that there is more solutions.
You can use string of VARCHAR2 as parameter and after that parse it with function like that:
PROCEDURE p_parse_into_array (
lv_str IN VARCHAR2,
lt_table IN OUT sys.dbms_debug_vc2coll,
lv_splitter IN VARCHAR2)
IS
ln_position NUMBER := 0;
ln_position_2 NUMBER;
ln_i NUMBER := 1;
BEGIN
ln_position_2 := INSTR(lv_str,lv_splitter,1,1);
WHILE ln_position_2 != 0
LOOP
lt_table.extend(1);
lt_table(ln_i) := SUBSTR(lv_str,ln_position+1,ln_position_2-ln_position-1);
ln_position := INSTR(lv_str,lv_splitter,1,ln_i);
ln_position_2 := INSTR(lv_str,lv_splitter,1,ln_i+1);
ln_i := ln_i + 1;
END LOOP;
END;
where lv_str is string to parse, lt_table is table of varchar(2000) and lv_splitter is character to split (, . ; - etc) and this function return values into lt_table, which you can use in you select menu.
Second solution is to use varray as you say, but there you need to use dynamic sql with command:
execute immediate 'select * from dual where some_value in (select * from table('||my_varray_table||'));
And other solution is to use nested table. It´s your choice, which of this solution you prefer :)

Stored procedure to replace certain variables in string

I'm working on a stored procedure that will accept a string and return a new string of text. Input parameters are #OrderId and #OrderText which is a string with dollar sign enclosed variables like so... $Order Name$ sent to $Customer$
The valid variables are in a Variables table (values such as Order Name, Customer, a total of 25 of them which should remain fairly static). Variables can only be used once in the string.
The stored procedure needs to return the string but with the variables replaced with their respective values.
Example1
Input: 123, $Order Name$ sent to $Customer$
Returns: Toolkit sent to StackCustomer Inc.
Example2
Input: 456, $Customer$ requests $delivery method$ for $order type$
Returns: ABC Inc requests fast shipping for pallet orders.
Each of the variables can be retrieved using a function.
DECLARE #OrderId int = 123
DECLARE #InputText VARCHAR(500) = '$Order Name$ sent to $Customer$'
select
#InputText = case when #InputText like '%$order name$%'
then replace(#InputText, '$Order Name$', getOrderName(id) else '' end,
#InputText = case when #InputText like '%$customer$'
then replace(#InputText, '$Customer$', getCustomer(id) else '' end
-- repeat 25 times
Is there a better way? My main concern is maintainability - if a variable is added, renamed, or removed, this stored proc will need to be changed (although I'm told it would only happen a couple times a year, if that). Would dynamic sql be able to help in this case?
Personally, I would create a keywords table to maintain it. something like this
CREATE TABLE [keywords] (
key_value VARCHAR(100) NOT NULL,
function_value VARCHAR(100) NOT NULL
)
INSERT INTO [keywords]
VALUES
('$Customer$','getCustomer(id)'),
('$Order Name$' ,'getOrderName(id)'),
('$order type$','getOrderType(id)')
Then use dynamic sql create REPLACE SQL
DECLARE #OrderId int = 123
DECLARE #InputText VARCHAR(500) = '$Order Name$ sent to $Customer$'
DECLARE #sql VARCHAR(8000) = 'SELECT '
SELECT
#sql = #sql +
' #InputText = replace(#InputText, ''' + key_value + ''', ' + function_value + ')'
+ ' ,'
FROM keywords
WHERE #InputText LIKE '%' + key_value + '%'
SELECT #sql = LEFT(#sql, LEN(#sql) -1)
PRINT #sql
EXEC(#sql)
SQLFiddle
I am not really getting why you need to do tokenization if you are going to use input variables for the procedure.
There are token templates already available for SQL Management Studio in the form of:
<(tokenName),(datatype),(defaultvalue)>
You can get their data filled directly with SQL Managment Studio with CTRL + SHIFT + M, or with ALT > Q > S in 2012, or by text finding their values in an environment.
If you are trying to put in an input to be accessed by an outside developing platform that changes the strings like ADO.NET or the Entity Framework in C#/VB.NET I still am not getting why you would not just make more input variables.
You could do this quite easily:
Declare #OrderPlace varchar(128), #Customer varchar(64), #StringCombine varchar(512);
Select
#OrderPlace = 'Place I am at'
, #Customer = 'Mr Customer';
Select #StringCombine = #Customer + ' order at ' + #OrderPlace
Then if a different language accessed your SQL server procedure it would just have to put in two parameters #Customer and #OrderPlace. You could even set #StringCombine to be an output variable. This is much more preferable then text replacing characters and then running a string. This could be able for SQL injection attacks potentially so santizing your inputs is a big part of returning data, especially if you are altering something for SQL to run before it is ran.
You mentioned maintainability and this is much more robust because if I change the logic to the proc but DO NOT change the variables names, I did not have to change anything else. If I have to change an ADO.NET or other library for references and then SQL code, that is lot more work. Generally when working with tokens I strive for reuse of code where one part of it can go down and only hurt that part of it, not take the whole thing down.

MySQL stored procedure looping control

I am looping over a cursor and have the standard exist loop control set however in the loop I also do select into from another table, if this search returns no results then that triggers the exit handler and the loop terminates.
My question is: How do I attached the continue handler for the loop to a cursor and ignore the select into or how do I get round this problem?
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_results=1;
.
.
.
search_loop:WHILE (no_more_results=0) DO
.
FETCH my_csr INTO something;
.
SELECT thing INTO my_thing FROM `dups` where `dups`.thing = thing_id;
The last select triggers the exit conditions...
Thanks
Paul
Since your code is expecting zero or one rows, use the SET syntax:
SET my_thing = (SELECT thing FROM dups where dups.thing = thing_id);
This will set my_thing to null if there are no rows.
I haven't tested this, so if it is still setting the handler, change to this, which always returns a row:
SET my_thing = SELECT IFNULL((SELECT thing FROM dups where dups.thing = thing_id), null);
Alternatively, you can convert your statement similarly:
SELECT IFNULL((SELECT thing FROM dups where dups.thing = thing_id), null) INTO my_thing;
I believe these alternatives are presented in order of readability.

SSRS multi-value parameter using a stored procedure

I am working on a SSRS report that uses a stored procedure containing a few parameters. I am having problems with two of the parameters because I want to have the option of selecting more than one item.
Here's a condensed version of what I have:
CREATE PROCEDURE [dbo].[uspMyStoredProcedure]
(#ReportProductSalesGroupID AS VARCHAR(MAX)
,#ReportProductFamilyID AS VARCHAR(MAX)
,#ReportStartDate AS DATETIME
,#ReportEndDate AS DATETIME)
--THE REST OF MY QUERY HERE WHICH PULLS ALL OF THE NEEDED COLUMNS
WHERE DateInvoicedID BETWEEN #ReportStartDate AND #ReportEndDate
AND ProductSalesGroupID IN (#ReportProductSalesGroupID)
AND ProductFamilyID IN (#ReportProductFamilyID)
When I try to just run the stored procedure I only return values if I enter only 1 value for #ReportProductSalesGroupID and 1 value #ReportProductFamilyID. If I try to enter two SalesGroupID and/or 2 ProductFamilyID it doesn't error, but I return nothing.
-- Returns data
EXEC uspMyStoredProcedure 'G23', 'NOF', '7/1/2009', '7/31/2009'
-- Doesn't return data
EXEC uspMyStoredProcedure 'G23,G22', 'NOF,ALT', '7/1/2009', '7/31/2009'
In SSRS I get an error that says:
Incorrect syntax near ','
It appears that the , separator is being included in the string instead of a delimiter
You need three things:
In the SSRS dataset properties, pass the multi-value param to the stored procedure as a comma-delimited string
=Join(Parameters!TerritoryMulti.Value, ",")
In Sql Server, you need a table-value function that can split a comma-delimited string back out into a mini table (eg see here). edit: Since SQL Server 2016 you can use the built-in function STRING_SPLIT for this
In the stored procedure, have a where clause something like this:
WHERE sometable.TerritoryID in (select Item from dbo.ufnSplit(#TerritoryMulti,','))
... where ufnSplit is your splitting function from step 2.
(Full steps and code in my blog post 'SSRS multi-value parameters with less fail'):
Let us assume that you have a multi value list #param1
Create another Internal Parameter on your SSRS report called #param2 and set the default value to:
=Join(Parameters!param1.value, 'XXX')
XXX can be any delimiter that you want, EXCEPT a comma (see below)
Then, you can pass #param2 to your query or stored procedure.
If you try to do it any other way, it will cause any string function that uses commas to separate arguments, to fail. (e.g. CHARINDEX, REPLACE).
For example Replace(#param2, ',', 'replacement') will not work. You will end up with errors like "Replace function requires 3 arguments".
Finally I was able to get a simple solution for this problem. Below I have provided all (3) steps that I followed.
I hope you guys will like it :)
Step 1 - I have created a Global Temp Table with one column.
CREATE GLOBAL TEMPORARY TABLE TEMP_PARAM_TABLE(
COL_NAME VARCHAR2(255 BYTE)
) ON COMMIT PRESERVE ROWS NOCACHE;
Step 2 - In the split Procedure, I didn't use any array or datatable, I have directly loaded the split values into my global temp table.
CREATE OR REPLACE PROCEDURE split_param(p_string IN VARCHAR2 ,p_separator IN VARCHAR2
)
IS
v_string VARCHAR2(4000);
v_initial_pos NUMBER(9) := 1;
v_position NUMBER(9) := 1;
BEGIN
v_string := p_string || p_separator;
delete from temp_param_policy;
LOOP
v_position :=
INSTR(v_string, p_separator, v_initial_pos, 1);
EXIT WHEN(NVL(v_position, 0) = 0);
INSERT INTO temp_param_table
VALUES (SUBSTR(v_string, v_initial_pos
, v_position - v_initial_pos));
v_initial_pos := v_position + 1;
END LOOP;
commit;
END split_param;
/
Step 3 - In the SSRS dataset parameters, I have used
=Join(Parameters!A_COUNTRY.Value, ",")
Step 4: In the start of your stored procedure executes the Procedure
Exec split_param(A_Country, ‘,’);
Step 5: In your stored procedure sql use the condition like below.
Where country_name in (select * from TEMP_PARAM_TABLE)
When SSRS passes the parameter it is in the form: Param1,Param2,Param3.
In the procedure, you just need to put identifiers around each parameter. And also identifiers around the value that is returned by the dataset. In my case, I used semicolons.
CREATE OR REPLACE PROCEDURE user.parameter_name (
i_multivalue_parameter
)
AS
l_multivalue_parameter varchar2(25555) := ';' || replace(i_multivalue_parameter,',',';') || ';';
BEGIN
select something
from dual
where (
instr(l_multivalue_parameter, ';' || database_value_that_is_singular || ';') > 0
)
END;
i_multivalue_parameter is passed in via SSRS.
l_multivalue_parameter reads the parameter passed in via SSRS and puts identifiers around each value.
database_value_that_is_singular is the value returned for each record.
So if 'Type1,Type2,Type3'is passed in via SSRS:
i_multivalue_parameter is: Type1,Type2,Type3
l_multivalue_parameter is: ;Type1;Type2;Type3;
database_value_that_is_singular is: ;Type1; or ;Type2; or ;Type3;
Instr will return a value over 0 if the parameter matches.
This works even if each parameters are similar. EG: "Type A" and "Type AA". That is "Type A" will not match "Type AA".
I found a simple way for my solution. Define the parameter value in the report as an expression like this
="'" + Join(Parameters!parm.Value,"','") + "'"
(in case you can't read it the first and last literals are double quote, single quote, double quote. The join literal is double quote, single quote, comma, single quote, double quote)
Then in the stored procedure you can use dynamic sql to create your statement. I did this to create a temp table of values to join to in a later query, like this:
CREATE #nametable (name nvarchar(64))
SET #sql = N'SELECT Name from realtable where name in (' + #namelist + ')'
INSERT INTO #nametable exec sp_executesql #sql
#namelist would be the name of the stored procedure parameter.