MySQL stored procedure issue, generate custom ID's - mysql

I had a stored procedure for making custom ID, but it was for SQL Server and I tried to convert it to MySQL with help of an online tool, and I get errors and I need help from you guys :(
This stored procedure will produce ID codes for my users, like for admin (AD001, AD002,...etc), first, it will look if there is no value it will generate the first value like (AD001) if there is a value it will get the value and increment it by 1.
This is my SQL Server version of the procedure which works:
create procedure admin_code
as
begin
declare #max int, #no varchar(50), #value varchar(50)
select #max = isnull(max(cast(right(id_user, 3) as int)), 0) + 1
from admin_information
if #max < 100
select #no = 'AD' + right('00000' + cast(#max as varchar(50)), 3)
else if #max >= 100
select #no = 'AD' + right('0' + cast(#max as varchar(50)), 4)
if #max >= 1000
select #no = 'AD' + right('0' + cast(#max as varchar(50)), 5)
print #no
select #no
return 0
end
And this is for MySQL
create procedure admin_code()
sp_lbl:
begin
declare v_max int;
declare no varchar(50);
declare value varchar(50);
select v_max=ISNULL( max(cast(RIGHT(id_user,3)as int)),0)+1 into v_max from admin_information;
if v_max <100 then
set v_no=CONCAT('AD',RIGHT('00000'+CAST(v_max as varchar(50)),3));
elseif
v_max>=100 then
-- SQLINES LICENSE FOR EVALUATION USE ONLY
set v_no=CONCAT('AD',RIGHT('0'+CAST(v_max as varchar(50)),4));
end if;
if v_max>=1000 then
-- SQLINES LICENSE FOR EVALUATION USE ONLY
set v_no=CONCAT('AD',RIGHT('0'+CAST(v_max as varchar(50)),5))
print;
end if; v_no
-- SQLINES LICENSE FOR EVALUATION USE ONLY
select v_no;
LEAVE sp_lbl 0;
end;
This is the online tool I used:
http://www.sqlines.com/online
Error:

Related

"DECLARE" is not valid at this position for this server version, expecting: ERROR

I tried every way possible to put the "DECLARE" in my procedural SQL query (Using MySQL Workbench) and its showing:
"DECLARE" is not valid at this position for this server version, expecting: ERROR.
Now I need help.
DELIMITER //
CREATE PROCEDURE getdetails()
BEGIN
DECLARE
vin table.vin%type;
responsetime table.responseTimeStamp%type;
odometer table.odometer%type;
chargePercentage table.soc%type;
CURSOR sequential_vehicle_status is
SELECT vin, responseTimeStamp, odometer, soc FROM table ORDER BY vin, responseTimeStamp;
OPEN sequential_vehicle_status;
LOOP
FETCH sequential_vehicle_status into vin, responseTimeStamp, odometer, chargePercentage;
EXIT WHEN sequential_vehicle_status%notfound;
dbms_output.put_line(vin || " * " || responseTimeStamp || " * " || odometer || " * " || chargePercentage || "% " ||);
END LOOP;
CLOSE sequential_vehicle_status;
END //
DELIMITER ;
This code will work. Here is a demo. Please adjust the declared variables to your table column types.
CREATE PROCEDURE getdetails()
BEGIN
DECLARE finished INTEGER DEFAULT 0; --this is added so the exit from loop can be made
DECLARE vin int;
DECLARE responseTimeStamp int;
DECLARE odometer int;
DECLARE chargePercentage int;
DECLARE sequential_vehicle_status
cursor for
SELECT vin
, responseTimeStamp
, odometer
, soc
FROM `table`
ORDER BY vin, responseTimeStamp;
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;--this is added so the exit from loop can be made
OPEN sequential_vehicle_status;
start_loop: LOOP
IF finished = 1 THEN
LEAVE start_loop;
END IF;
FETCH sequential_vehicle_status into vin
, responseTimeStamp
, odometer
, chargePercentage;
select concat(vin, '*', responseTimeStamp, '*', odometer, '*', chargePercentage, '% ');
END LOOP;
CLOSE sequential_vehicle_status;
END;
Please read the comments to your question. DBMS_OUTPUT is oracle package.
Instead of that dbms_output line of code you can add this:
select concat(vin, '*', responseTimeStamp, '*', odometer, '*', chargePercentage, '% ');
You are combining mysql and oracle syntax both.
Dbms_output is package in oracle and IS clause is used in oracle to create cursor.
CREATE PROCEDURE getdetails()
BEGIN
DECLARE vin table.vin%type;
DECLARE responsetime table.responseTimeStamp%type;
DECLARE odometer table.odometer%type;
DECLARE chargePercentage table.soc%type;
DECLARE CURSOR sequential_vehicle_status for
SELECT vin, responseTimeStamp, odometer, soc FROM table ORDER BY vin, responseTimeStamp;
Also if you want to print something to console use select instead dbms_output which is oracle package.
ie. SELECT concat('VIN is ', vin);

How should I do to properly use the sp_msforeachDB to create and delete backups

I'm setting up a new way to create and delete backups in our internal environments. The space on the servers is a big issue so i really have to find a way to do a backup and delete the older one for each database, procedurally.
I came up with the idea of using the sp_MSforeachdb and simply do a backup. On success, it would delete the older backup that was done the day before. (we do 1 backup per night).
DECLARE #DBOPurpose Varchar(15)
DECLARE #Drive Varchar(1)
Set #DBOPurpose = 'Omnilabs'
DECLARE #command varchar(Max)
Select #command = '
If Exists (Select *
from sys.databases
where name like ''%?''
and name like ''%'+#DBOPurpose+'%'')
BEGIN
EXECUTE master.dbo.xp_create_Subdir '+#Drive+':\SQLBACKUP\'+#DBOPurpose+'
GO
BACKUP DATABASE [?] TO DISK = '+#Drive+':\SQLBackup\'+#DBOPurpose+'_Select Cast(Cast(Year(Getdate())As Varchar(150))+''_''+Cast(month(Getdate())As Varchar(150))+''_''+Cast (Day(Getdate()) As Varchar(150))+''_''+ cast(DATEPART(hour, GETDATE()) as varchar) + '''' + cast(DATEPART(minute, GETDATE()) as varchar)+ '''' + cast(DATEPART(Second, GETDATE()) as varchar)+ ''.bak'' As varchar(150))
END
Print N''TEST''
'
--Select #Command
EXEC sp_MSforeachdb #command
I was expecting that doing Select #Command would actually show me something, but its null. When I run this, it simply writes "Commands completed successfully." within a second, which doesn't make any sense.
Just saw my error, which was only caused by the hyphens that were not placed correctly. Here's the code:
If exists(Select * from #TempDBName where DBNAME = #DBOPurpose)
BEGIN
DECLARE #ERROR bit
DECLARE #command nvarchar(Max)
SET #Error = 0
SET #command = '
DECLARE #DBO VARCHAR(15)
Set #DBO = ''%'+#DBOPURPOSE+'%''
If Exists (Select *
from sys.databases
where name like ''%?''
and name like ''%''+#DBO+''%'')
BEGIN TRY
PRINT ''?''
EXECUTE master.dbo.xp_create_Subdir '''+#Drive+':\SQLBACKUP\TEST\?''
BACKUP DATABASE [?] TO DISK = '''+#Drive+':\SQLBackup\'+#DBOPurpose+'_' +(Cast(Cast(Year(Getdate())As Varchar(150))+'_'+Cast(month(Getdate())As Varchar(150))+'_'+Cast (Day(Getdate()) As Varchar(150))+'_'+ cast(DATEPART(hour, GETDATE()) as varchar) + cast(DATEPART(minute, GETDATE()) as varchar)+ cast(DATEPART(Second, GETDATE()) as varchar)+ '.bak''' As varchar(150)))+'
END TRY
BEGIN CATCH
Insert into BackupExecLog(ErrorDate, ErrorNumber, ErrorMessage)
Select Getdate(),
ERROR_NUMBER() as ErrorNumber,
ERROR_MESSAGE() as ErrorMessage
Set #Error = 1
END CATCH'
Select #Command
--EXEC sys.sp_MSforeachdb #command

PHP like $$var in T-SQL (SQL Server 2008)

Is there any way to execute something like php $$var ..?
Which will make the value of a var as var name.
I have been googling for many hours ant cant find any that satisfy my needs.
Thanks.
edit:
currently what I want to achieve is something similar to this
declare #table1 table(Name Varchar(100))
declare #table2 table(Name Varchar(100))
...
declare #table10 table(Name Varchar(100))
declare #int1 int
set #int1 = 0
while #int1 < 10
begin
select #[table + #int1]
END
Since the example in the question isn't valid T-SQL, it's not clear whether you want to select the value of #[table + #int1], or from the table (i.e. select name from #[table + #int1]) - I'm assuming here that it's the second one.
One approach would be to have a single table with an indicator column classifying the rows:
declare #table table(Name Varchar(100), groupid int)
...
declare #int1 int
set #int1 = 0
while #int1 < 10
begin
select name from #table WHERE groupid = #int1
set #int1 = #int1 + 1
end

Shuffle a string with mysql/sql

I was wondering, if there is some way to shuffle the letters of a string in mysql/sql, i.e. something like the pseudocode: SELECT SHUFFLE('abcdef')?
Couldn't find any from http://dev.mysql.com/doc/refman/5.0/en/string-functions.html and searching for it just seems to find solutions for shuffling results, not a string.
Here you go:
DELIMITER //
DROP FUNCTION IF EXISTS shuffle //
CREATE FUNCTION shuffle(
v_chars TEXT
)
RETURNS TEXT
NOT DETERMINISTIC -- multiple RAND()'s
NO SQL
SQL SECURITY INVOKER
COMMENT ''
BEGIN
DECLARE v_retval TEXT DEFAULT '';
DECLARE u_pos INT UNSIGNED;
DECLARE u INT UNSIGNED;
SET u = LENGTH(v_chars);
WHILE u > 0
DO
SET u_pos = 1 + FLOOR(RAND() * u);
SET v_retval = CONCAT(v_retval, MID(v_chars, u_pos, 1));
SET v_chars = CONCAT(LEFT(v_chars, u_pos - 1), MID(v_chars, u_pos + 1, u));
SET u = u - 1;
END WHILE;
RETURN v_retval;
END;
//
DELIMITER ;
SELECT shuffle('abcdef');
See sqlfiddle.com for the output.
Tested successfully with mariadb 10.1 (mysql 5.6 equivalent)
Edit: this solution is for Microsoft SQL Server.
As it's not allowed to use RAND() in user defined function, we create a view to use it later in our shuffle function:
CREATE VIEW randomView
AS
SELECT RAND() randomResult
GO
The actual shuffle function is as following:
CREATE FUNCTION shuffle(#string NVARCHAR(MAX))
RETURNS NVARCHAR(MAX) AS
BEGIN
DECLARE #pos INT
DECLARE #char CHAR(1)
DECLARE #shuffeld NVARCHAR(MAX)
DECLARE #random DECIMAL(18,18)
WHILE LEN(#string) > 0
BEGIN
SELECT #random = randomResult FROM randomView
SET #pos = (CONVERT(INT, #random*1000000) % LEN(#string)) + 1
SET #char = SUBSTRING(#string, #pos, 1)
SET #shuffeld = CONCAT(#shuffeld, #char)
SET #string = CONCAT(SUBSTRING(#string, 1, #pos-1), SUBSTRING(#string, #pos+1, LEN(#string)))
END
RETURN #shuffeld
END
Calling the function
DECLARE #string NVARCHAR(MAX) = 'abcdefghijklmnonpqrstuvwxyz0123456789!"ยง$%&/()='
SELECT dbo.shuffle(#string)
There is nothing in standard SQL - your best bet is probably to write a user defined function

How to CREATE TYPE type_name AS existing_table_name

Is there a way to create table type in SQL Server 2008 based on scheme of existing table?
CREATE TABLE A (id INT, name VARCHAR(30))
CREATE TYPE type_a AS TABLE.A
Something like that.
No, this kind of composable DML is not yet possible. Microsoft has rejected this suggestion in the past, but with enough votes (e.g. more than 1!) it may get reconsidered in the future:
http://connect.microsoft.com/SQLServer/feedback/details/294130/table-valued-parameters-add-support-for-create-type-type-from-table-table-name-options-syntax-construct
You can use following stored procedure to create a type with same schema existing table may have.
Create PROCEDURE [dbo].[Sp_DefineTypeOutOfTableSchema]
#TableNames NVARCHAR(500)
AS
BEGIN
DECLARE #TableName NVARCHAR(100)
DECLARE #strSQL NVARCHAR(max)
DECLARE #strSQLCol NVARCHAR(1000)
DECLARE #ColName NVARCHAR(100)
DECLARE #ColDataTaype NVARCHAR(50)
DECLARE #ColDefault NVARCHAR(50)
DECLARE #ColIsNulable NVARCHAR(50)
DECLARE #ColCharMaxlen NVARCHAR(50)
DECLARE #ColNumPrec NVARCHAR(50)
DECLARE #ColNumScal NVARCHAR(50)
IF LEN(#TableNames) > 0 SET #TableNames = #TableNames + ','
WHILE LEN(#TableNames) > 0
BEGIN
SELECT #TableName = LTRIM(SUBSTRING(#TableNames, 1, CHARINDEX(',', #TableNames) - 1))
DECLARE schemaCur CURSOR FOR
SELECT COLUMN_NAME,DATA_TYPE,IS_NULLABLE,COLUMN_DEFAULT,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =#TableName
OPEN schemaCur
SELECT #strSQL=''
FETCH NEXT FROM schemaCur
INTO #ColName,#ColDataTaype,#ColIsNulable,#ColDefault,#ColCharMaxlen,#ColNumPrec,#ColNumScal
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #strSQLCol=''
SELECT #strSQLCol= '['+#ColName+'] '+'[' + #ColDataTaype +'] '
IF #ColDataTaype='nvarchar' or #ColDataTaype='char' or #ColDataTaype='varchar' or #ColDataTaype='vchar'
BEGIN
SELECT #strSQLCol=#strSQLCol+ '(' + #ColCharMaxlen +') '
END
ELSE IF #ColDataTaype='numeric' or #ColDataTaype='decimal'
BEGIN
SELECT #strSQLCol=#strSQLCol +'(' + #ColNumPrec +',' +#ColNumScal + ') '
END
IF #ColIsNulable='YES'
BEGIN
SELECT #strSQLCol=#strSQLCol+ 'NULL '
END
ELSE
BEGIN
SELECT #strSQLCol=#strSQLCol+ ' NOT NULL '
END
IF #ColDefault IS NOT NULL
BEGIN
SELECT #strSQLCol=#strSQLCol+ ' DEFAULT(' +#ColDefault + '),'
END
ELSE
BEGIN
SELECT #strSQLCol=#strSQLCol+ ' ,'
END
SELECT #strSQL=#strSQL+#strSQLCol
--print #strSQL
FETCH NEXT FROM schemaCur
INTO #ColName,#ColDataTaype,#ColIsNulable,#ColDefault,#ColCharMaxlen,#ColNumPrec,#ColNumScal
END
CLOSE schemaCur
DEALLOCATE schemaCur
--print #strSQL
SELECT #strSQL=left( #strSQL, len(#strSQL)-1)
--print #strSQL
IF EXISTS (SELECT * FROM sys.types WHERE IS_TABLE_TYPE = 1 AND name = 't_' +#TableName)
BEGIN
EXEC('DROP TYPE t_' +#TableName )
END
SELECT #strSQL = 'CREATE TYPE t_' + #TableName + ' AS TABLE (' + #strSQL + ')'
--print #strSQL
EXEC (#strSQL)
SELECT #TableNames = SUBSTRING(#TableNames, CHARINDEX(',', #TableNames) + 1, LEN(#TableNames))
END
END
you can use it like this
Exec Sp_DefineTypeOutOfTableSchema 'Table1name,Table2name'
You could experiment with creating a function that pulled the table definition out of sysobjects, systypes, syscolumns, syscomments, etc., and built a CREATE statement out of it. You'd just have to make sure to grab all of the important pieces (columns, constraints, comments, etc.) from the various sys tables.
Then call it like... EXEC myCREATEtable #template_table_name or some such...