I want to create a stored procedure which will do matching of two tables. My requirement is to match two tables based on the columns user passes as an input.
Syntax:
CREATE PROCEDURE reconcile.matchTables(
IN TAB1 VARCHAR(25),
IN TAB1 VARCHAR(25),
IN COLS1 VARCHAR(250) ,
IN COLS2 VARCHAR(250))
EX:
matchTables('table1', 'table2', 'col1#col2#col3#col4' , 'col2#col13#col1#col8')
Now the stored procedure should form the where clause like the following
table1.col1 = table2.col2
and table1.col2 = table2.col13
and table1.col3 = table2.col1
and table1.col4 = table2.col8
MySQL does not include a function to split a delimited string. However, it’s very easy to create your own function.
User define function:
CREATE [AGGREGATE] FUNCTION function_name
RETURNS {STRING|INTEGER|REAL|DECIMAL}
Function:
CREATE FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '');
Usage:
SELECT SPLIT_STR(string, delimiter, position)
Answer
Table 1
CREATE TABLE `Table1` (
`Col1` varchar(100) DEFAULT NULL,
`Col2` varchar(100) DEFAULT NULL,
`Col3` varchar(100) DEFAULT NULL,
`Col4` varchar(100) DEFAULT NULL,
`DummyColumn` varchar(45) DEFAULT NULL
)
Table 2
CREATE TABLE `Table2` (
`col2` varchar(100) DEFAULT NULL,
`col13` varchar(100) DEFAULT NULL,
`col1` varchar(100) DEFAULT NULL,
`col8` varchar(100) DEFAULT NULL
)
Stored Procedure
CREATE DEFINER=`Connect7827`#`%` PROCEDURE `reconcile.matchTables`(
IN TAB1 VARCHAR(25),
IN TAB2 VARCHAR(25),
IN COLS1 VARCHAR(250) ,
IN COLS2 VARCHAR(250))
StartfromHere: BEGIN
DECLARE NoOfColumnInTable1 INT unsigned DEFAULT 0;
DECLARE NoOfColumnInTable2 INT unsigned DEFAULT 0;
Declare Column1Count int default 1;
Declare Column2Count int default 1;
Declare vPickOneValue varchar(100);
Declare querystring varchar(8000);
Declare NoOFRowsInFinalResult int default 1;
Declare _Tab1 varchar(1000);
Declare _TAB2 varchar(1000);
Declare _COLS1 varchar(1000);
Declare _COLS2 varchar(1000);
-- Column Names for Table 1
DROP TEMPORARY TABLE IF EXISTS Table1_Columns;
CREATE TEMPORARY TABLE Table1_Columns(Column_Name varchar(100));
SET #buffer= CONCAT_WS('','insert into Table1_Columns(Column_Name)
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = ',"'",TAB1,"'");
-- Select #buffer;
PREPARE stmt FROM #buffer;
EXECUTE stmt;
-- Column Names for Table 2
DROP TEMPORARY TABLE IF EXISTS Table2_Columns;
CREATE TEMPORARY TABLE Table2_Columns(Column_Name varchar(100));
SET #buffer= CONCAT_WS('','insert into Table2_Columns(Column_Name)
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = ',"'",TAB2,"'");
-- Select #buffer;
PREPARE stmt FROM #buffer;
EXECUTE stmt;
Set NoOfColumnInTable1=(Select count(*) from Table1_Columns);
Set NoOfColumnInTable2=(Select count(*) from Table2_Columns);
-- Select NoOfColumnInTable1,NoOfColumnInTable2;
if (NoOfColumnInTable1=0) then
Select 'Table 1 not found in database'as'Result';
leave StartfromHere;
end if;
if (NoOfColumnInTable2=0) then
Select 'Table 2 not found in database' as'Result' ;
leave StartfromHere;
end if;
IF (NoOfColumnInTable1!=NoOfColumnInTable2) then
Select 'No of column to be joined must be equal.'as'Result';
leave StartfromHere;
end if;
DROP TEMPORARY TABLE IF EXISTS BasedOn_Col1_List;
CREATE TEMPORARY TABLE BasedOn_Col1_List(ID int NOT NULL AUTO_INCREMENT, Column_Name varchar(100), PRIMARY KEY (id));
while Column1Count< NoOfColumnInTable1+1 do
set #Query=CONCAT_WS('' ,"insert into BasedOn_Col1_List(Column_Name) Select SUBSTRING_Index('",COLS1,"','#',",Column1Count,");");
-- Select #Query as'Value';
PREPARE stmt1 FROM #Query;
EXECUTE stmt1;
SET Column1Count=Column1Count+1;
end while;
SET Column1Count=1;
WHILE Column1Count<=NoOfColumnInTable1 do
SET vPickOneValue=(Select Concat(Column_Name,"#") from BasedOn_Col1_List where ID=Column1Count);
update BasedOn_Col1_List set Column_Name=replace(Column_Name,vPickOneValue,"") where ID<>Column1Count;
-- Select vPickOneValue;
SET Column1Count=Column1Count+1 ;
end while;
-- Preapre Table from Column2 Parameter
DROP TEMPORARY TABLE IF EXISTS BasedOn_Col2_List;
CREATE TEMPORARY TABLE BasedOn_Col2_List(ID int NOT NULL AUTO_INCREMENT, Column_Name varchar(100), PRIMARY KEY (id));
while Column2Count< NoOfColumnInTable2+1 do
set #Query=CONCAT_WS('' ,"insert into BasedOn_Col2_List(Column_Name) Select SUBSTRING_Index('",COLS2,"','#',",Column2Count,");");
-- Select #Query as'Value';
PREPARE stmt2 FROM #Query;
EXECUTE stmt2;
SET Column2Count=Column2Count+1;
end while;
SET Column2Count=1;
WHILE Column2Count<=NoOfColumnInTable2 do
SET vPickOneValue=(Select Concat(Column_Name,"#") from BasedOn_Col2_List where ID=Column2Count);
update BasedOn_Col2_List set Column_Name=replace(Column_Name,vPickOneValue,"") where ID<>Column2Count;
-- Select vPickOneValue;
SET Column2Count=Column2Count+1 ;
end while;
DROP TEMPORARY TABLE IF EXISTS TableFromColumnList;
CREATE TEMPORARY TABLE TableFromColumnList
( ID int NOT NULL AUTO_INCREMENT,
Table1Name varchar(100),
Column_Name_Table1 varchar(100),
Table2Name varchar(1000),
Column_Name_Table2 varchar(100),
PRIMARY KEY (id)
);
Insert into TableFromColumnList(Column_Name_Table1,Column_Name_Table2,Table1Name,Table2Name)
select t1.Column_Name,t2.Column_Name,TAB1,TAB2
from BasedOn_Col1_List t1 , BasedOn_Col2_List t2 where t1.Id=t2.id;
-- -- Preparing the final Result ----------------
While NoOFRowsInFinalResult<=NoOfColumnInTable2 do -- / Or NoOFRowsInFinalResult<=NoOfColumnInTable2 --
SET _Tab1 =(Select Table1Name from TableFromColumnList where Id=NoOFRowsInFinalResult);
SET _COLS1 =(Select Column_Name_Table1 from TableFromColumnList where Id=NoOFRowsInFinalResult);
SET _TAB2 =(Select Table2Name from TableFromColumnList where Id=NoOFRowsInFinalResult);
SET _COLS2 =(Select Column_Name_Table2 from TableFromColumnList where Id=NoOFRowsInFinalResult);
IF NoOFRowsInFinalResult=1 then
SET querystring =concat_ws("" , querystring,_Tab1,".", _COLS1 , "=",_Tab2,".", _COLS2," ");
else
SET querystring =concat_ws("" , querystring ,"and",_Tab1,".", _COLS1 , "=" ,_Tab2,".", _COLS2 ," ");
end if;
SET NoOFRowsInFinalResult=NoOFRowsInFinalResult+1 ;
End while;
SET querystring=concat_ws("","Select * from ",TAB1,", " ,TAB2," where ",querystring);
Select querystring;
END
CREATE PROCEDURE matchTables
#TAB1 VARCHAR(25),
#TAB2 VARCHAR(25),
#COLS1 VARCHAR(250) ,
#COLS2 VARCHAR(250)
AS
BEGIN
DECLARE #WHEREstring VARCHAR(MAX)
SET #WHEREstring =
'
WHERE
'
SELECT #WHEREstring = #WHEREstring + #TAB1 +'.'+ tab1.col+' = '+#TAB2+'.' + tab2.col +' AND
'
FROM
(
SELECT QUOTENAME(split.a.value('.','VARCHAR(100)')) AS col, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowNum
FROM
(
SELECT Cast ('<M>' + Replace(#COLS1, '#', '</M><M>')+ '</M>' AS XML) AS Tab1Data
) AS A
CROSS apply Tab1Data.nodes ('/M') AS Split(a)
) tab1
INNER JOIN
(
Select QUOTENAME(AliasSplit.c.value('.', 'varchar(100)')) AS col, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowNum
FROM
(
SELECT Cast ('<A>' + Replace(#COLS2, '#', '</A><A>')+ '</A>' AS XML) AS Tab2Data
) AS A
CROSS apply Tab2Data.nodes ('/A') AS AliasSplit(c)
) tab2
ON tab1.RowNum = tab2.RowNum
SET #WHEREstring= LEFT(#WHEREstring, LEN(#WHEREstring) - 8)
print #WHEREstring
END
Now, execute it using :::
EXEC matchTables 'table1', 'table2', 'col1#col2#col3#col4' , 'col2#col13#col1#col8'
i hope you got the desired where clause. cheers
You can build your own function:
CREATE FUNCTION String_split(inp VARCHAR(255),del VARCHAR(255),loc INT)
RETURNS VARCHAR(255)
RETURN REPLACE(Substring(Substring_index(inp, del,loc),LENGTH(Substring_index(inp, del, loc-1)) + 1),del, '');
CHAR_LENGTH - return correct length in chars
CREATE FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
CHAR_LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '');
Related
In MySQL offcial document for count,there are descriptions as below:
For MyISAM tables, COUNT(*) is optimized to return very quickly if the SELECT retrieves from one > table, no other columns are retrieved, and there is no WHERE clause. For example:
mysql> SELECT COUNT(*) FROM student;
This optimization only applies to MyISAM tables, because an exact row count is stored for this >storage engine and can be accessed very quickly. COUNT(1) is only subject to the same >optimization if the first column is defined as NOT NULL.
I want to test it for myself, and make a test as below,I make a table called system_user and the first column is type,all the value of type is null,however when I use SELECT COUNT(1) and SELECT COUNT(*) to query, I found the time cost is nearly the same,even if tried for serval times.
I am wonder why the first column is null and the optimization in MyISAM is still working?
When I use SQL_NO_CACHE,the time cost is still nearly the same:
related table:
CREATE TABLE `system_user` (
`type` varchar(10) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(8) NOT NULL,
`age` int(11) DEFAULT NULL,
`tag` varchar(8) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
related procdure to create massive data:
DELIMITER $$
USE `test`$$
DROP PROCEDURE IF EXISTS `add_user_batch`$$
CREATE DEFINER=`root`#`%` PROCEDURE `add_user_batch`(IN COUNT INT)
BEGIN
DECLARE i INT;
DECLARE t_name VARCHAR(8);
DECLARE t_tag VARCHAR(20);
DECLARE t_age INT(2);
DECLARE t_sql_template VARCHAR(100);
DECLARE t_sql TEXT;
DECLARE t_tag_mod_val INT DEFAULT(25);
DECLARE t_commit_mod_val INT DEFAULT(100);
DECLARE t_start_time DATETIME;
DECLARE t_end_time DATETIME;
TRUNCATE TABLE `system_user`;
SET t_start_time=NOW();
SET t_sql_template = “INSERT INTO `system_user`(NAME, age, tag) VALUES“;
SET t_sql = t_sql_template;
SET i = 1;
WHILE i <= COUNT
DO
SET t_age = FLOOR(1 + RAND() * 60);
SET t_name = LEFT(UUID(), 8);
IF MOD(i, t_tag_mod_val) = 0 THEN
SET t_tag = “NULL“;
ELSE
SET t_tag = CONCAT(“'“,LEFT(UUID(), 8),“'“);
END IF;
SET t_sql = CONCAT(t_sql,“('“,t_name,“',“,t_age,“,“,t_tag,“)“);
IF MOD(i,t_commit_mod_val) != 0 THEN
SET t_sql = CONCAT(t_sql,“,“);
ELSE
SET t_sql = CONCAT(t_sql,“;“);
SET #insert_sql = t_sql;
PREPARE stmt FROM #insert_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
COMMIT;
SET t_sql=t_sql_template;
END IF;
SET i = i + 1;
END WHILE;
IF LENGTH(t_sql) > LENGTH(t_sql_template) THEN
SET t_sql=CONCAT(SUBSTRING(t_sql,1,LENGTH(t_sql)-1),';');
SET #insert_sql = t_sql;
PREPARE stmt FROM #insert_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
COMMIT;
END IF;
SET t_end_time=NOW();
SELECT CONCAT('insert data success,time cost ',TIMEDIFF(t_end_time,t_start_time)) AS finishedTag;
END$$
DELIMITER ;
In Postgresql, trigger can be created by using trigger procedure. This is handy way of creating trigger. Using the same trigger procedure, it is possible to create several triggers and apply it even for several different tables. I am wondering if there is any MySQL equivalent for it. I am inspired by this blog post which creates a generic trigger for database auditing. My plan is to implement the similar approach by using MySQL. But, is it really possible create that kind of generic trigger by MySQL?
After doing some research, I have understood that there is no direct way to create generic trigger in MySQL. Even dynamic SQL like prepare statement, execute statement are not allowed inside trigger in MySQL.
I have found a workaround to generate trigger dynamically. Suppose we have a customer table:
CREATE TABLE customer (
id bigint(20) NOT NULL AUTO_INCREMENT,
created_on datetime DEFAULT NULL,
first_name varchar(100) NOT NULL,
last_name varchar(100) NOT NULL,
PRIMARY KEY (id)
)
A revision info table:
CREATE TABLE REVINFO (
REV int(11) NOT NULL AUTO_INCREMENT,
REVTSTMP bigint(20) DEFAULT NULL,
PRIMARY KEY (REV)
)
An audit table:
CREATE TABLE customer_AUD (
id bigint(20) NOT NULL,
REV int(11) NOT NULL,
REVTYPE tinyint(4) DEFAULT NULL,
created_on datetime DEFAULT NULL,
first_name varchar(100) DEFAULT NULL,
last_name varchar(100) DEFAULT NULL,
PRIMARY KEY (id, REV),
KEY FK_REV (REV)
)
Now we will crate a procedure that will take a table name and generate SQL for create audit related trigger for table.
DROP PROCEDURE IF EXISTS `proc_trigger_generator`;
DELIMITER $$
CREATE PROCEDURE `proc_trigger_generator` (IN tableName VARCHAR(255))
BEGIN
DECLARE triggerSQL TEXT DEFAULT "";
DECLARE cols TEXT DEFAULT "";
DECLARE col_values TEXT DEFAULT "";
DECLARE insert_query TEXT DEFAULT "";
DECLARE colName TEXT DEFAULT "";
DECLARE done INT DEFAULT FALSE;
DECLARE cursorDS CURSOR FOR SELECT column_name FROM information_schema.columns cols
WHERE cols.table_name = CONCAT(tableName, '_AUD')
and (column_name != 'REV' && column_name != 'REVTYPE');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET triggerSQL = 'DELIMITER ;; \n\n';
SET triggerSQL = CONCAT(triggerSQL, 'drop trigger if exists tr_', tableName, '_update_audit;; \n\n');
SET triggerSQL = CONCAT(triggerSQL, 'create trigger tr_', tableName, '_update_audit \n');
SET triggerSQL = CONCAT(triggerSQL, 'after update \n');
SET triggerSQL = CONCAT(triggerSQL, '\t on ', tableName, '\n');
SET triggerSQL = CONCAT(triggerSQL, 'for each row \n');
SET triggerSQL = CONCAT(triggerSQL, 'begin \n');
SET triggerSQL = CONCAT(triggerSQL, '\t DECLARE tmpInt INT; \n');
SET triggerSQL = CONCAT(triggerSQL, '\t SELECT COALESCE(MAX(REV), 0) FROM REVINFO into tmpInt; \n\n');
SET triggerSQL = CONCAT(triggerSQL, '\t INSERT INTO REVINFO (REV, REVTSTMP) VALUES (tmpInt+1, CURRENT_TIMESTAMP()); \n\n');
SET insert_query = CONCAT(insert_query, 'INSERT INTO ', CONCAT(tableName, '_AUD'), ' (');
OPEN cursorDS;
ds_loop: LOOP
FETCH cursorDS INTO colName;
IF done THEN
LEAVE ds_loop;
END IF;
SET cols = CONCAT(cols, colName, ', ');
SET col_values = CONCAT(col_values, 'new.', colName, ', ');
END LOOP;
SET insert_query = CONCAT(insert_query, cols, 'REV, REVTYPE) VALUES \n');
SET insert_query = CONCAT(insert_query, '\t\t(', col_values, 'tmpInt+1, 1', ');');
CLOSE cursorDS;
SET triggerSQL = CONCAT(triggerSQL, '\t ',insert_query, ' \n\n');
SET triggerSQL = CONCAT(triggerSQL, 'end;; \n\n');
SET triggerSQL = CONCAT(triggerSQL, 'DELIMITER ; \n\n');
SELECT triggerSQL;
END $$
DELIMITER ;
call proc_trigger_generator('customer');
Calling the procedure by using customer table name generates SQL for the desired trigger:
DELIMITER ;;
drop trigger if exists tr_customer_update_audit;;
create trigger tr_customer_update_audit
after update
on customer
for each row
begin
DECLARE tmpInt INT;
SELECT COALESCE(MAX(REV), 0) FROM REVINFO into tmpInt;
INSERT INTO REVINFO (REV, REVTSTMP) VALUES (tmpInt+1, CURRENT_TIMESTAMP());
INSERT INTO customer_AUD (id, created_on, first_name, last_name, REV, REVTYPE) VALUES
(new.id, new.created_on, new.first_name, new.last_name, tmpInt+1, 1);
end;;
DELIMITER ;
The above trigger should do auditing tasks for customer table.
The trigger generator procedure can be applied to any other table now that we wish to apply auditing related tasks.
I'm working on an Android program that introduces in a table approximately 15000 integer values(somewhere between 350-500 lines with 32 columns). In the DB I also have other similar values. This 15000 values that I'm talking about represent a processed image, so basically I want to compare the similarity of two images. Now, when I try to compare the values of two images(I'm comparing value by value and count the equal ones), only the data writing process takes about 7 minutes, which is way too long(I want to be able to write and compare at least 5 images in that time). I know that usually you don't work with this kind of things directly in the DB, but do you think that there is anything that I can do, or is it necessary to do this comparison on the server? The values returned by the descriptor came as line elements separated by ',' and each line is separated by ';'. I take each returned element and save it in a tables column. Here is my code:
Split function:
CREATE DEFINER=`root`#`localhost` FUNCTION `strSplit`(textIn longtext, delim varchar(12), count int) RETURNS int(11)
BEGIN
declare splitString INT(11);
SET splitString = replace(substring(substring_index(textIn, delim, count), length(substring_index(textIn, delim, count - 1)) + 1), delim, '');
RETURN splitString;
END
The function that creates the table:
CREATE TABLE IF NOT EXISTS `myguide`.`objectlocation` (
`ObjectLocationId` INT(11) NOT NULL AUTO_INCREMENT,
`ValueObject` LONGTEXT NOT NULL,
`DescriptorSize` INT(11) NOT NULL,
`DescriptionObject` VARCHAR(45) NOT NULL,
`DataInsert` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`InsertBy` VARCHAR(45) NULL DEFAULT NULL,
PRIMARY KEY (`ObjectLocationId`))
ENGINE = InnoDB
AUTO_INCREMENT = 2
DEFAULT CHARACTER SET = utf8
And this is the code that does the insert part:
CREATE DEFINER=`root`#`localhost` PROCEDURE `myguide_sp_info_imageId`(descriptorIn longtext, sizeDescriptor INT)
BEGIN
declare sizeImagesTable INT DEFAULT (select count(*) from objectLocation);
declare descriptorSizeImage INT;
declare descriptor INT;
declare sizeDescriptorImage INT DEFAULT sizeDescriptor;
declare contorInsertImage INT default 1;
declare descriptorForSplit longtext;
declare descriptorImageSaved longtext;
declare descriptorForSplitImageSaved longtext;
/* check if table exist, drop*/
DROP TEMPORARY TABLE IF EXISTS backupObjectLocation;
/* Create temporar table for store info about objectLocation*/
CREATE TEMPORARY TABLE backupObjectLocation (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
idImage int NOT NULL,
descriptorSaved longtext not null,
sizeDescriptorSaved float not null
);
/* check if table exist, drop*/
DROP TEMPORARY TABLE IF EXISTS processImage;
/* Create temporar table for store info about objectLocation*/
CREATE TEMPORARY TABLE processImage (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
descriptorSaved varchar(255) ,
descriptorReceived varchar(255)
);
SET descriptorImageSaved = RTRIM(descriptorIn);
SET descriptorForSplit = REPLACE(descriptorImageSaved, ';', ',');
INSERT INTO backupObjectLocation (idImage, descriptorSaved, sizeDescriptorSaved)
SELECT ObjectLocationId, ValueObject, DescriptorSize FROM objectLocation;
loop_insertDescriptorImage: LOOP
if contorInsertImage > sizeDescriptorImage then
leave loop_insertDescriptorImage;
end if;
SET descriptor = strSplit(descriptorForSplit, ',', contorInsertImage);
INSERT INTO processImage (descriptorReceived) VALUES (descriptor);
SET contorInsertImage = contorInsertImage + 1;
ITERATE loop_insertDescriptorImage;
end LOOP;
loop_table: LOOP
if sizeImagesTable > 1 then
leave loop_table;
end if;
SET descriptorSizeImage = (SELECT sizeDescriptorSaved from backupObjectLocation where id = sizeImagesTable);
loop_image: LOOP
if descriptorSizeImage > 1 then
leave loop_image;
end if;
SET descriptorImageSaved = (SELECT descriptorSaved from backupObjectLocation where id = sizeImagesTable);
SET descriptorForSplitImageSaved = REPLACE(descriptorImageSaved, ';', ',');
SET descriptorSizeImage = descriptorSizeImage + 1;
ITERATE loop_image;
end LOOP;
SET sizeImagesTable = sizeImagesTable + 1;
ITERATE loop_table;
end LOOP;
select descriptorImageSaved;
select * from backupObjectLocation;
select * from processImage;
END
Please help me find a solution.
I made a query to populate my table and converted it into a stored procedure.
CREATE PROCEDURE [dbo].[sp_getSAPCMTX]
#sSDate varchar(10),
#sEDate varchar(10),
#sBranch varchar(4000)
AS
DELETE FROM SAPCMTX
WHERE DocDate BETWEEN #sSDate AND #sEDate AND
StoreCode IN (SELECT Item FROM dbo.SplitStrings(#sBranch , ','))
INSERT INTO SAPCMTX
SELECT * FROM Table T0
WHERE T0.DocDate BETWEEN #sSDate AND #sEDate AND T0.DataSource<>'O' AND
T1.TreeType<>'I' AND T0.DocType = 'I' AND
StoreCode IN COLLATE DATABASE_DEFAULT IN (SELECT Item FROM
dbo.SplitStrings(#sBranch , ','))
GO
To run it I used this command
EXEC [dbo].[sp_getSAPCMTX]
#sSDate = '3/8/2016',
#sEDate = '3/8/2016',
#sBranch = '002'
It returns 33 rows but when I try to run it separately as a TSQL it returns 34 row.
DECLARE #sSDate varchar(10)
DECLARE #sEDate varchar(10)
DECLARE #sBranch varchar(4000)
SET #sSDate = '3/8/2016'
SET #sEDate = '3/8/2016'
SET #sBranch = '002'
DELETE FROM SAPCMTX
WHERE DocDate BETWEEN #sSDate AND #sEDate AND
StoreCode IN (SELECT Item FROM dbo.SplitStrings(#sBranch , ','))
INSERT INTO SAPCMTX
SELECT * FROM Table T0
WHERE T0.DocDate BETWEEN #sSDate AND #sEDate AND T0.DataSource<>'O' AND
T1.TreeType<>'I' AND T0.DocType = 'I' AND
StoreCode IN COLLATE DATABASE_DEFAULT IN (SELECT Item FROM
dbo.SplitStrings(#sBranch , ','))
GO
Any idea why there is a difference in the result considering it is essentially the same query?
Here you have two possibilities that could help you getting the desired results:
SET ANSI_NULLS ON before altering the procedure:
SET ANSI_NULLS ON
GO
ALTER PROCEDURE [dbo].[sp_getSAPCMTX]
-- your code of the procedure
Create local properties and copy the value of the parameters into them:
ALTER PROCEDURE [dbo].[sp_getSAPCMTX]
#sSDate VARCHAR(10)
#sEDate VARCHAR(10)
#sBranch VARCHAR(4000)
AS
DECLARE #sDate VARCHAR(10)
DECLARE #eDate VARCHAR(10)
DECLARE #branch VARCHAR(4000)
SET #sDate = #sSDate
SET #eDate = #sEDate
SET #branch = #sBranch
-- your code of the procedure
I am trying to write one procedure, i am getting syntax error. I was trying to fix the same with the help of net, but failed.
Here is my stored procedure. Any help please?
The scenario is i am trying to take workspaceid column values from table hotelings and trying to make that value as my column for another table. Then i am trying to update the same column value with ; for a given start and end time of hoteling table in newly created table2.
My two tables are
CREATE TABLE `hotelings` (
`HotelingId` int(11) NOT NULL AUTO_INCREMENT,
`Description` longtext,
`StartDate` datetime NOT NULL,
`EndDate` datetime NOT NULL,
`BookedBy` longtext,
`BookingType` int(11) NOT NULL,
`RepeatType` longtext,
`RepeatDay` longtext,
`ProjectId` int(11) NOT NULL,
`WorkSpaceId` int(11) NOT NULL,
`starttime` varchar(45) DEFAULT NULL,
`endtime` varchar(45) DEFAULT NULL,
PRIMARY KEY (`HotelingId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `hotelingtime` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Time` time DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
and my procedure is:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_procedure`()
BEGIN
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(CASE WHEN workspaceid = ''',
workspaceid,
''' then "" ELSE NULL end) AS ',
CONCAT('`',workspaceid,'`')
)
) INTO #sql
FROM sms.hotelings;
SET #sql = CONCAT('CREATE TABLE IF NOT EXISTS table2 AS SELECT t.Time as Time, ', #sql, ' FROM sms.hotelings h, sms.hotelingtime t
GROUP BY t.Time');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
begin
declare num_rows int;
declare i int;
declare col_name varchar(50);
declare v varchar(10);
DECLARE v_finished INTEGER DEFAULT 0;
-- cursor to fetch column names
DECLARE col_names CURSOR FOR
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'table2'
ORDER BY ordinal_position;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
OPEN col_names;
temp_hotelingloop: LOOP
FETCH col_names INTO col_name;
IF v_finished = 1 THEN
LEAVE temp_hotelingloop;
END IF;
begin
declare starttime time;
declare endtime time;
-- cursor to fetch start and end for a given workspaceid
DECLARE startendTime CURSOR FOR
SELECT starttime, endtime from hotelings
where workspaceid = col_name;
OPEN startendTime;
FETCH startendTime INTO starttime, endtime;
-- i am getting error here and not giving me the result.
SET #sql = CONCAT('update table2 set ''',#col_name ,''' = '';'' where time between ''',#starttime,''' and ''',#endtime,'''');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
CLOSE startendTime;
end;
SET i = i + 1;
END LOOP temp_hotelingloop;
CLOSE col_names;
end;
select * from table2;
DROP TABLE table2;
END
Any help please?
Thanks in advance
SET #sql = CONCAT('update table2 set ''',#col_name ,''' = '';'' where time between ''',#starttime,''' and ''',#endtime,'''');
You are using #col_name here, but on your declaration missing the #
declare col_name varchar(50);