Building and Testing with MySQL Workbench for SSMS People - mysql

I am great with Microsoft's SQL Server and SQL Server Management Studio (SSMS).
I'm trying to get things I used to do there to work in MySQL Workbench, but it is giving me very unhelpful errors.
Currently, I am trying to write an INSERT statement. I want to declare my variables and test it with a few values, then turn the end result into a stored procedure.
Right now, I have a syntax error that is not allowing me to continue, and the error message is not helpful either:
syntax error, unexpected DECLARE_SYM
There is no error list at the bottom and no way to copy the text of that error to the clipboard, so it all has to be studied on one screen, then flip to this screen so I can write it down.
Irritating!
The MySQL documentation surely has what I'm looking for, but I can learn much faster by doing than spending weeks reading their online manual.
DELIMITER $$
declare cGroupID char(6) DEFAULT = 'ABC123';
declare subGroupRecords int;
declare nDocTypeID int(11);
declare bDocActive tinyint(1) DEFAULT '1';
declare cDocID varchar(256) DEFAULT NULL;
insert into dbo_connection.documents
(group_id, subgroup_id, type_id, active, title, doc_id, priority, ahref, description, last_modified)
values
(cGroupID,cSubGroupID,nDocTypeID,bDocActive,cTitle,cDocID,0,ahref1, docDesc,NOW());
select * from dbo_connection.documents where group_id='ABC123';
END
So, for right now, I'm looking for why MySQL does not like my declare statement.
For the long term, I'm interested in finding a short article that shows a cookbook approach to doing some of the basic tasks that SQL developers would need (i.e. skips the Hello World program and discussion on data types).

DECLARE is only valid within stored programs. In other words, unlike T-SQL, you can't build up your query and then wrap CREATE PROCEDURE around it to turn the end result into a stored procedure, you have to build it up as a stored procedure from the get-go.

Related

Syntax error in converting SQL Server trigger to MySQL

I have to convert SQLServer trigger to MySQL. I was trying to recreate it in MySQL but the thing is that I get syntax error every time I try different combinations and I don't know what's not working and why.
I'm creating cinema database and the following trigger is started when an entry is removed from the Hall table. Suppose a hall is being renovated and we have to move the performances in that hall to other locations. In this case, they are moved to a hall with an index 1 smaller than the distant hall.
Here is SQLServer query:
CREATE TRIGGER tDeleteHall ON Hall
FOR DELETE
AS
BEGIN
DECLARE #id int
SELECT #id = id_hall FROM deleted
UPDATE Spectacle set id_hall = #id - 1
END
DELETE FROM Hall WHERE id_hall = 3;
MySQL code
CREATE TRIGGER tDeleteHall BEFORE DELETE ON Hall
DECLARE #id int
SELECT #id = id_hall FROM deleted
UPDATE Spectacle set id_hall = #id - 1
END
DELETE FROM Spectacle WHERE id_hall = 3;
The error I'm getting:
ERROR: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECLARE #id int
SELECT #id = id_sala FROM deleted
UPDATE Spectacle set id_hall = ' at line 2
It's not totally clear what this trigger is supposed to do. But here's a MySQL trigger that I think does the same thing.
CREATE TRIGGER tDeleteHall BEFORE DELETE ON Hall
FOR EACH ROW
BEGIN
UPDATE Spectacle SET id_hall = OLD.id_hall - 1;
END
MySQL does not have the deleted pseudo-table. Instead, it uses OLD.<column> to refer to the deleted row, or in INSERT and UPDATE triggers, use the NEW.<column> to refer to the new row version.
MySQL's triggers are always row triggers, not statement triggers as in SQL Server. Nevertheless, MySQL triggers require the FOR EACH ROW syntax. Perhaps someday they will also support statement triggers.
You don't need to DECLARE a local variable for the example you show. But if you do use a local variable, know that unlike SQL Server, local variables in MySQL routines must not use the # sigil.
MySQL has two types of variables:
Local variables, which do not use the # sigil. These are created with DECLARE, and assigned a data type. They are local to the code block they are declared in.
User-defined session variables, which do use the # sigil. You can use these inside triggers, but they are not local. In other words, the value you set will remain set in your session after the trigger is done. These variables are created when you set them, so you don't declare them with DECLARE. They don't have a data type.
Statements inside the code block must be terminated with ;. This creates an ambiguity because the CREATE TRIGGER statement itself needs to be terminated. But if you run this in a client that assumes that ; terminates the CREATE TRIGGER, and there are ; characters in the body of the trigger, it becomes confused. The solution is to use DELIMITER to change the terminator of the CREATE TRIGGER, then you can use ; inside the body. You should read https://dev.mysql.com/doc/refman/8.0/en/stored-programs-defining.html
On the other hand, if you execute CREATE TRIGGER using a query interface that only processes the input one statement at a time anyway, there's no ambiguity, so you don't need to change the DELIMITER. Examples would be most query APIs.
Stored routines in MySQL are quite different from SQL Server. You need to make an effort to read the documentation and study examples. It's not an efficient use of your time or ours to try to learn complex syntax via Stack Overflow.

how to cross check all the tables in MYSQL database [duplicate]

Is there a mySQL query to search all tables within a database?
If not can you search all tables within a database from the mySQL workbench GUI?
From phpmyadmin there's a search panel you can use to select all tables to search through. I find this super effective since magento, the ecommerce package I'm working with has hundreds of tables and different product details are in different tables.
Alternatively, if your database is not that huge, you can make a dump and make your search in the .sql generated file.
If you want to do it purely in MySQL, without the help of any programming language, you could use this:
## Table for storing resultant output
CREATE TABLE `temp_details` (
`t_schema` varchar(45) NOT NULL,
`t_table` varchar(45) NOT NULL,
`t_field` varchar(45) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
## Procedure for search in all fields of all databases
DELIMITER $$
#Script to loop through all tables using Information_Schema
DROP PROCEDURE IF EXISTS get_table $$
CREATE PROCEDURE get_table(in_search varchar(50))
READS SQL DATA
BEGIN
DECLARE trunc_cmd VARCHAR(50);
DECLARE search_string VARCHAR(250);
DECLARE db,tbl,clmn CHAR(50);
DECLARE done INT DEFAULT 0;
DECLARE COUNTER INT;
DECLARE table_cur CURSOR FOR
SELECT concat('SELECT COUNT(*) INTO #CNT_VALUE FROM `',table_schema,'`.`',table_name,'` WHERE `', column_name,'` REGEXP ''',in_search,''';')
,table_schema,table_name,column_name
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA NOT IN ('information_schema','test','mysql');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
#Truncating table for refill the data for new search.
PREPARE trunc_cmd FROM "TRUNCATE TABLE temp_details;";
EXECUTE trunc_cmd ;
OPEN table_cur;
table_loop:LOOP
FETCH table_cur INTO search_string,db,tbl,clmn;
#Executing the search
SET #search_string = search_string;
SELECT search_string;
PREPARE search_string FROM #search_string;
EXECUTE search_string;
SET COUNTER = #CNT_VALUE;
SELECT COUNTER;
IF COUNTER>0 THEN
# Inserting required results from search to table
INSERT INTO temp_details VALUES(db,tbl,clmn);
END IF;
IF done=1 THEN
LEAVE table_loop;
END IF;
END LOOP;
CLOSE table_cur;
#Finally Show Results
SELECT * FROM temp_details;
END $$
DELIMITER ;
Source: http://forge.mysql.com/tools/tool.php?id=232
If you are using MySQL Workbench, you can do this by doing right click on the DB Schema you want to search into, and then "Search Table Data...".
In there you can select the "Search using REXEXP" option, and then type your text of search as usual. It will provide the DB rows matching your specific text.
You will need to check the "Search columns of all types" box as well.
In MySQL Workbench you can use the Table Data Search feature. It can search across multiple tables and/or multiple databases.
Search string in all tables on a database is a complex task. Normally you don't need to use exactly all tables and results are complex to read without a specific layout (tree of tables with matches or the like)
SQL Workbench/J offers a GUI and a command-line version to do such task:
More info:
http://www.sql-workbench.net/manual/wb-commands.html#command-search-data
http://www.sql-workbench.net/manual/dbexplorer.html#search-table-data
NOTE: Search with JDBC driver uses a lot of memory if it is not configured properly. SQL Workbench/J warns about that and although online documentation is a bit outdated, the sources of documentation (doc/xml/db-problems.xml) explain how to fix it for different BBDD:
Here an extract for Postgres:
The PostgreSQL JDBC driver defaults to buffer the results obtained from the database
in memory before returning them to the application. This means that when retrieving data, &wb-productname; uses (for a short amount of time) twice as much memory as really needed. This also means that WbExport or WbCopy will
effectively read the entire result into memory before writing it into the output file.
For large exports, this is usually not wanted.
This behavior of the driver can be changed so that the driver uses cursor based retrieval.
To do this, the connection profile must disable the "Autocommit" option and must define a default fetch size that is greater than zero. A recommended value is e.g. 10, it might be that higher numbers give a better performance. The number defined for the fetch size,
defines the number of rows the driver keeps in its internal buffer before requesting more
rows from the backend.

Microsoft Access - stored procedure with cursor

I have a stored procedure in SQL Server that I am using to delete duplicates from one of the tables.
This stored procedure makes use of a cursor.
I tried to create the same stored procedure in Microsoft Access by just replacing the 'CREATE PROCEDURE' with 'CREATE PROC' but it didn't seem to work.
Can anyone provide some workaround?
Here is the SQL Server stored procedure:
ALTER PROCEDURE [dbo].[csp_loginfo_duplicates]
AS
BEGIN
SET NOCOUNT ON;
declare #minrowid bigint
declare #empid nvarchar(15)
declare #dtpunched datetime
declare #count tinyint
declare curDuplicate cursor for
select empid,dtpunched,count(*),min(row_id) from loginfo
group by empid,dtpunched
having count(*)>1
open curDuplicate
fetch next from curduplicate into #empid,#dtpunched,#count,#minrowid
while (##fetch_status=0)
begin
delete from loginfo where empid=#empid and dtpunched=#dtpunched and row_id<>#minrowid
fetch next from curduplicate into #empid,#dtpunched,#count,#minrowid
end
close curDuplicate
deallocate curDuplicate
END
Beginning with Jet 4 (Access 2000), Access DDL includes support for CREATE PROCEDURE when you execute the DDL statement from ADO. However, those "procedures" are limited compared to what you may expect based on your SQL Server experience. They can include only one SQL statement, and no procedural type code. Basically an Access stored procedure is the same as a saved query, and is therefore subject to the same limitations which include the fact that Access' db engine doesn't speak T-SQL.
As for a workaround, you could create an Access-compatible DELETE statement to remove the duplicates. But I would first look for "the simplest thing which could possibly work".
Run your stored procedure on SQL Server to remove the duplicates.
Create a unique constraint to prevent new duplicates of the empid/dtpunched pairs in your loginfo table.
In your Access application, create a link to the SQL Server loginfo table.
However, I have no idea whether that suggestion is appropriate for your situation. If you give us more information to work with, chances are you will get a better answer.

mySQL query to search all tables within a database for a string?

Is there a mySQL query to search all tables within a database?
If not can you search all tables within a database from the mySQL workbench GUI?
From phpmyadmin there's a search panel you can use to select all tables to search through. I find this super effective since magento, the ecommerce package I'm working with has hundreds of tables and different product details are in different tables.
Alternatively, if your database is not that huge, you can make a dump and make your search in the .sql generated file.
If you want to do it purely in MySQL, without the help of any programming language, you could use this:
## Table for storing resultant output
CREATE TABLE `temp_details` (
`t_schema` varchar(45) NOT NULL,
`t_table` varchar(45) NOT NULL,
`t_field` varchar(45) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
## Procedure for search in all fields of all databases
DELIMITER $$
#Script to loop through all tables using Information_Schema
DROP PROCEDURE IF EXISTS get_table $$
CREATE PROCEDURE get_table(in_search varchar(50))
READS SQL DATA
BEGIN
DECLARE trunc_cmd VARCHAR(50);
DECLARE search_string VARCHAR(250);
DECLARE db,tbl,clmn CHAR(50);
DECLARE done INT DEFAULT 0;
DECLARE COUNTER INT;
DECLARE table_cur CURSOR FOR
SELECT concat('SELECT COUNT(*) INTO #CNT_VALUE FROM `',table_schema,'`.`',table_name,'` WHERE `', column_name,'` REGEXP ''',in_search,''';')
,table_schema,table_name,column_name
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA NOT IN ('information_schema','test','mysql');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
#Truncating table for refill the data for new search.
PREPARE trunc_cmd FROM "TRUNCATE TABLE temp_details;";
EXECUTE trunc_cmd ;
OPEN table_cur;
table_loop:LOOP
FETCH table_cur INTO search_string,db,tbl,clmn;
#Executing the search
SET #search_string = search_string;
SELECT search_string;
PREPARE search_string FROM #search_string;
EXECUTE search_string;
SET COUNTER = #CNT_VALUE;
SELECT COUNTER;
IF COUNTER>0 THEN
# Inserting required results from search to table
INSERT INTO temp_details VALUES(db,tbl,clmn);
END IF;
IF done=1 THEN
LEAVE table_loop;
END IF;
END LOOP;
CLOSE table_cur;
#Finally Show Results
SELECT * FROM temp_details;
END $$
DELIMITER ;
Source: http://forge.mysql.com/tools/tool.php?id=232
If you are using MySQL Workbench, you can do this by doing right click on the DB Schema you want to search into, and then "Search Table Data...".
In there you can select the "Search using REXEXP" option, and then type your text of search as usual. It will provide the DB rows matching your specific text.
You will need to check the "Search columns of all types" box as well.
In MySQL Workbench you can use the Table Data Search feature. It can search across multiple tables and/or multiple databases.
Search string in all tables on a database is a complex task. Normally you don't need to use exactly all tables and results are complex to read without a specific layout (tree of tables with matches or the like)
SQL Workbench/J offers a GUI and a command-line version to do such task:
More info:
http://www.sql-workbench.net/manual/wb-commands.html#command-search-data
http://www.sql-workbench.net/manual/dbexplorer.html#search-table-data
NOTE: Search with JDBC driver uses a lot of memory if it is not configured properly. SQL Workbench/J warns about that and although online documentation is a bit outdated, the sources of documentation (doc/xml/db-problems.xml) explain how to fix it for different BBDD:
Here an extract for Postgres:
The PostgreSQL JDBC driver defaults to buffer the results obtained from the database
in memory before returning them to the application. This means that when retrieving data, &wb-productname; uses (for a short amount of time) twice as much memory as really needed. This also means that WbExport or WbCopy will
effectively read the entire result into memory before writing it into the output file.
For large exports, this is usually not wanted.
This behavior of the driver can be changed so that the driver uses cursor based retrieval.
To do this, the connection profile must disable the "Autocommit" option and must define a default fetch size that is greater than zero. A recommended value is e.g. 10, it might be that higher numbers give a better performance. The number defined for the fetch size,
defines the number of rows the driver keeps in its internal buffer before requesting more
rows from the backend.

Mysql Stored Procedures Dynamic Queries

I've had quite a few problems and know that I can get some good answers here!
Ok kinda 2 part question.
Part 1 I'm doing some really big updating of data, kind rejiging the tables mostly.
so the question is should I be using a mysql stored procedure or mysql/php like normal.
I'm currently on the stored producure frame of mind.
Reasons are
a) Quicker
b) No timeouts.
If anyone has any other opinions let me know.
P.S we are talking about a big heap of data. LIKE over 1.5 million rows
2nd part.
In stored procedures how do I make a query that will only return one row just give me that row. Also the query is a little dynamic so like
SET tag_query = concat('SELECT tag_id FROM tags WHERE tag = "',split_string_temp,'"');
Any clues?
I can't seem to find anything just easy about this language!
Thanks in advance for your help.
Richard
Your question is a little vague, so I'll just respond to the one piece of code you included.
If you want to get a tag_id from a tag name, I would recommend a stored function instead of a stored procedure.
Something like this:
DELIMITER $$
DROP FUNCTION IF EXISTS GET_TAG_ID $$
CREATE FUNCTION GET_TAG_ID(P_TAG_NAME varchar(255)) RETURNS int
BEGIN
DECLARE v_return_val INT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_return_val = -1;
IF (P_TAG_NAME IS NULL)
THEN
RETURN NULL;
END IF;
select tag_id
into v_return_val
from TAGS
where tag = P_TAG_NAME;
RETURN v_return_val;
END $$
DELIMITER ;
To update data once (not as a regular task) I would prefer using a gui admin like phpmyadmin or sqlyog issuing SQL commands directly (with a good backup of course!) as you can see the results quickly and don't need to worry with other things than your main task.