Regular Sudoku solver in MySQL

Both SQL-server and MySQL didn't cope with Recursive solvers. The flattened solver works, albeit a bit slow.

Stored Procedure


CREATE PROCEDURE `sudokuflat`(
	IN `given` char(81)
)
labelBegin: begin
declare r0    int default 0;
declare c0    int default 0;/*can be negative*/
declare r1    int default 0;
declare c1    int default 0;
declare rb    int default 0;
declare cb    int default 0;
declare r2    int default 0;
declare c2    int default 0;
declare n     int default 0;
declare nprev int default 0;/*convert from char*/
declare fnd   int default 0;
declare fnd2  int default 0;
declare tmp   char(81);
	
	set tmp = given;

	while r0 < 9 do
		set c0 = 0;
		while c0 < 9 do
			if substr(tmp,r0*9+c0+1,1)='0' then
				/*reset booleans TinyInt*/
				set fnd2 = 0;
				set n = 0;
				/*set to last highest tested*/
				if nprev <> 0 then
					set n = nprev;
					set nprev = 0;/*reset immediately*/
				end if;
				labelN: while n < 9 do
					set n = n + 1;/*because of "continue" increase here*/
					set fnd = 0;
					/*checks*/
					set r1 = 0;
					labelA: while r1<9 do
						if r0<>r1 and substr(tmp,r1*9+c0+1,1)=n then
							set fnd = 1;
							leave labelA;
						end if;
						set r1 = r1 + 1;
					end while;
					if fnd=1 and n<9 then 
						iterate labelN;
					end if;
					set c1 = 0;
					labelB: while c1<9 do
						if c0<>c1 and substr(tmp,r0*9+c1+1,1)=n then
							set fnd = 1;
							leave labelB;
						end if;
						set c1 = c1 + 1;
					end while;
					if fnd=1 and n<9 then 
						iterate labelN;
					end if;
					set rb = FLOOR(r0/3)*3;
					set cb = FLOOR(c0/3)*3;
					set r2 = rb;
					labelC: while rb+3>r2 do
						set c2 = cb;
						while cb+3>c2 do
							if (r0<>r2 or c0<>c2) and substr(tmp,r2*9+c2+1,1)=n then
								set fnd = 1;
								leave labelC;
							end if;
							set c2 = c2 + 1;
						end while;
						set r2 = r2 + 1;
					end while;
					if fnd=1 and n<9 then
						iterate labelN;
					end if;
					/*try it*/
					if fnd=1 then 
						leave labelN;/*n must be 9*/
					end if;
					
					set tmp = CONCAT(substr(tmp,1,r0*9+c0),n,substr(tmp,r0*9+c0+2,81));
					set fnd2 = 1;
					leave labelN;/*and continue*/
					/*intelligent undo below; with recursion it was undone here*/
				end while;
				if fnd2=0 and fnd=1 and n=9 then
					/*undo current position*/
					set tmp = CONCAT(substr(tmp,1,r0*9+c0),'0',substr(tmp,r0*9+c0+2,81));
					/*extra step back*/
					if c0=0 then
						set r0 = r0 - 1;
						set c0 = 8; /*see below*/
					else set c0 = c0 - 1;
					end if;
					while substr(given,r0*9+c0+1,1)<>'0' or substr(tmp,r0*9+c0+1,1)='9' do
						/*if the last entered number was a 9, go even further back*/
						if substr(given,r0*9+c0+1,1)='0' and substr(tmp,r0*9+c0+1,1)='9' then 
							set tmp = CONCAT(substr(tmp,1,r0*9+c0),'0',substr(tmp,r0*9+c0+2,81));
						end if;
						/*extra step back*/
						if c0=0 then
							set r0 = r0 - 1;
							set c0 = 8; /*see below*/
						else set c0 = c0 - 1;
						end if;
					end while;
					set nprev = cast(substr(tmp,r0*9+c0+1,1) as unsigned);
					/*undo backtrack also */
					set tmp = CONCAT(substr(tmp,1,r0*9+c0),'0',substr(tmp,r0*9+c0+2,81));
					set c0 = c0 - 1;/*contra below*/
				end if;
			end if;
			set c0 = c0 + 1;/*this is meant by below*/
		end while;
		set r0 = r0 + 1;
	end while;
	if instr(tmp,'0')=0 then
		INSERT INTO sudokutable(sudoku) VALUES(tmp);
	end if;
end

Usage


SET @@SESSION.max_sp_recursion_depth = 255;

delete from sudokutable;

CALL `sudokuflat`('000000030050607004008903760000000520000216000042000000087302100200108090030000000');

select sudoku from sudokutable;

Takes about what feels like a minute... ;)