Después de encontrar la solución para que funcione el LIMIT de MySQL en Microsoft SQL Server ahora sigue el turno de modificar el código de Codeigniter para así tener algo transparente para nuestras consultas SQL.
Lo primero que se debe de hacer es modificar la librería de carga del Codeigniter, ( $this->load-> )
Vamos a trabajar en la carpeta: /system/application/libraries/ y creamos un archivo llamado: MY_Loader.php con el siguiente código:
< ?php
class MY_Loader extends CI_Loader{
/**
* Constructor, calls parent constructor.
*/
function MY_Loader()
{
parent::CI_Loader();
}/**
* Database Loader
*
* @access public
* @param string the DB credentials
* @param bool whether to return the DB object
* @param bool whether to enable active record (this allows us to override the config setting)
* @return object
*/
function database($params = '', $return = FALSE, $active_record = FALSE)
{
// Do we even need to load the database class?
if (class_exists('CI_DB') AND $return == FALSE AND $active_record == FALSE)
{
return FALSE;
}require_once(BASEPATH.'database/DB'.EXT);
// Load the DB class
$db =& DB($params, $active_record);$my_driver = config_item('subclass_prefix').'DB_'.$db->dbdriver.’_driver’;
$my_driver_file = APPPATH.’libraries/’.$my_driver.EXT;if (file_exists($my_driver_file))
{
require_once($my_driver_file);
$db =& new $my_driver(get_object_vars($db));
}if ($return === TRUE)
{
return $db;
}
// Grab the super object
$CI =& get_instance();// Initialize the db variable. Needed to prevent
// reference errors with some configurations
$CI->db = ”;
$CI->db = $db;
// Assign the DB object to any existing models
$this->_ci_assign_to_models();
}}
La idea de este archivo es extender la funcionalidad de carga de los drivers para la base de datos, despues en la misma carpeta de libraries creamos un archivo llamado: MY_DB_mssql_driver.php ya que estamos usando el driver mssql para nuestra conexión SQL Server
< ?php
class MY_DB_mssql_driver extends CI_DB_mssql_driver {
function __construct($params){
parent::__construct($params);
log_message('debug', 'Extended DB driver class instantiated!');
}function _limit($sql, $limit, $offset){
if($offset == 0){
return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
}else{
$OrderBy = "ORDER BY ";
if (count($this->ar_orderby) > 0){
$OrderBy .= implode(‘, ‘, $this->ar_orderby);if ($this->ar_order !== FALSE)
{
$OrderBy .= ($this->ar_order == ‘desc’) ? ‘ DESC’ : ‘ ASC’;
}
}else{
$OrderBy .= “(SELECT 1)”;
}$sql = preg_replace(‘/(\\’. $OrderBy .’\n?)/i’,”, $sql);
$sql = preg_replace(‘/(^\SELECT (DISTINCT)?)/i’,'\\1 ROW_NUMBER() OVER (‘.$OrderBy.’) AS rownum, ‘, $sql);
return “SELECT * \nFROM (\n” . $sql . “) AS A \nWHERE A.rownum BETWEEN (” .($offset + 1) . “) AND (“.($offset + $limit).”)”;
}
}
Y listo! con esto nuestra consulta LIMIT será transparente y se usará como siempre: $this->db->limit(2,10);
Aca les dejo las fuentes de esta información:
Así como suena el titulo, en Microsoft SQL Server no existe la función limit , para implementarla tienes que usar algunos trucos con subconsultas., algo tan sencillo en MySQL como: SELECT * FROM miTabla LIMIT 2,10 en SQL Server se vuelve una calamidad.
Buscando en Internet, encontré en Foros del Web una explicación de como hacer funcionar, se tiene que poner una subconsulta SQL con algo que diga: ROW_NUMBER() OVER (ORDER BY campo) as NumRows y despues se hace un WHERE con su respectivo Between para poner el limite: WHERE NumRows BETWEEN 2 AND 10
Aca un ejemplo más elaborado:
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY mi_Campo1) AS NumRows, *
FROM mi_Tabla
) as AS_NumRows
WHERE AS_NumRows.NumRows BETWEEN 10 AND 20
Si se requiere algún WHERE en nuestra consulta SQL se debe de meter en la subquery, en caso que no tengamos ningun campo a ordenar se cambia lo que tiene ROW_NUMBER, ORDER BY por la siguiente información:
ROW_NUMBER() OVER (ORDER BY (SELECT 1))
Y listo!.., no he probado el rendimiento pero pues aquí una solución extra.
Nota mental: Función replace de MySQL.
update TABLA set CAMPO = replace(CAMPO,’TEXTO_A_ENCONTRAR’,'TEXTO_REMPLAZAR’);
Y despues meter algun where si es necesario, es sensible a mayusculas y minusculas.
Si al hacer un insert les marca el siguiente error en MySQL:
Cannot add or update a child row: a foreign key constraint fails
La solución es cambiar el motor de almacenamiento MyISAM a InnoDB de la tabla que tiene la referencia, una vez realizado este cambio ya debe de funcionar el insert (claro, siempre y cuando exista el valor del ID que hace referencia).
Aca pueden ver más información sobre las relaciones de tablas en MySQL
Si por alguna razón se les olvido la contraseña del usuario ROOT en MySQL existe una opción sencilla para cambiarla, el unico requisito es claro tener privilegios de root en su distribución de linux favorita, ya sea ubuntu, debian, centos, etc… en estos ejemplos usaremos Ubuntu (ó Debian debe de jalar igual)
El paso 1 es detener el servidor MySQL,
/etc/init.d/mysql stop
Despues iniciar MySQL saltando la autentificación y deshabilitando la escucha de la red, digo por aquello de los hackers, con el siguiente comando tambien habilitamos el servicio en background (con el amperson se indica eso)
mysqld –skip-grant-tables –skip-networking &
Ahora si, nos conectamos al servidor de MySQL, especificamente la tabla mysql
mysql mysql -u root
Y pues a ejecutar el siguiente comando:
UPDATE user SET password=PASSWORD(‘mi_nueva_clave’) WHERE user=”root”;
quit;
Y listo!, matamos el proceso y reiniciamos mysql normalmente., para ver el proceso cuando lo lanzamos en background nos aparecio un número del proceso.
kill -9 NUMERO
Y listo!, a iniciar el servicio (quizas con el restart mata el proceso, pero mejor el kill para estar seguros):
/etc/init.d/mysql restart
A disfrutar del MySQL y claro! no olvidar la clave! jeje.
Si alguna vez tuvieron la necesidad de importar o exportar su base de datos de MySQL sin usar PHPMyAdmin o algún otro manejador de la base de datos, y pues deben de utilizar la linea de comandos, aquí pongo el mini-howto.
Para exportar una base de datos:
#Para ver la base de datos a exportar
mysql -u root -p
mysql > show database;
#Y fuera del shell del mysql ejecutar el comando mysqldump con el nombre de la base de datos
mysqldump -u usuario -p nombre_base_de_datos > archivo.sql
Para importar una base de datos se usa el siguiente comando:
#Para crear la base de datos por si no viene el comando en el archivo SQL
mysql -u root -p
mysql> create database nombre_base_de_datos;
#Ahora fuera del shell del mysql se ejecuta el comando inverso al mysqldump
mysql -u root -p nombre_base_de_datos < ruta_base_de_datos.sql
Despues de reiniciar la MacBook al querer ingresar al phpmyadmin me marcaba un error que la contraseña era incorrecta, y pues claro que era la correcta ya que es la que siempre se habia utilizado, y para rematar el mensaje de error me aparecia:
La conexión para controluser, como está definida en su configuración, fracasó.
Ahora bien, para resetear la contraseña tuve que utilizar estos comandos:
sudo launchctl stop org.macports.mysql5
sudo -u mysqld /opt/local/libexec/mysqld –skip-grant-tables
Con estos dos primeros matamos el proceso del mysql y con el otro iniciamos el proceso pero ignorando las tablas de privilegios, despues ingresamos al mysql como root
mysql -u root
Y ejecutamos estos 2 comandos dentro de la consola del mysql
UPDATE mysql.user SET Password=PASSWORD(‘password’) WHERE User=’root’
FLUSH PRIVILEGES;
Y listo!! con esto reseteamos al usuario root con la contraseña: password
Ahora para quitar el mensaje de phpmyadmin, buscamos el archivo config.inc.php y en la linea donde aparece:
$cfg['Servers'][$i]['controluser'] = ”;
$cfg['Servers'][$i]['controlpass'] = ”;
Nos aseguramos que esten vacios!! y listo!!. todo como nuevo!., aunque no estaría mal revisar que todas las tablas esten en buen estado!.
Uno de los problemas que tenia es que cada vez que iniciaba la Mac, al momento de cargar el XAMPP me pedia contraseña de root, y pues una o dos veces esta bien pero diario es una lata!.., así que la mejor opción es iniciar como servicio de sistema, así nos evitamos la molestia de poner la clave del xampp para arrancar el apache, mysql.
Se debe de crear un archivo con privilegios de root y grupo wheel (root:wheel) en la siguiente carpeta: /Library/LaunchDaemons/ y se debe de llamar: org.apachefriends.xampp.plist quedando algo así:
**/Library/LaunchDaemons/org.apachefriends.xampp.plist**
Y pues ponemos el siguiente contenido:
< ?xml version="1.0" encoding="UTF-8"?>
< !DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
KeepAlive
Label
org.apachefriends.xampp
ProgramArguments
/Applications/XAMPP/xamppfiles/xampp
start
QueueDirectories
RunAtLoad
WatchPaths
Y listo!! reiniciamos la MacOSX y debe de jalar!, igual si queremos probar directo desde consola poner el siguiente comando (como administrador).
**launchctl load /Library/LaunchDaemons/org.apachefriends.xampp.plist**
Y otra vez listo! a disfrutar de Apache
Como mi memoria es mala, mala!, y a veces necesito importar bases de datos grandes, ya que para exportar me gusta el phpmyadmin…, aquí pongo los comandos para tenerlos a la mano.
Para exportar MySQL es con el comando mysqldump y la sintaxis es la siguiente:
mysqldump -u usuario -p nombre_base_de_datos > archivorespaldo.sql
Ahora bien, para importar archivos grandes donde el phpmyadmin no lo permita, ya sea por las limitantes del PHP, el Apache!, la Red, etc, etc…, aquí esta el comando magico!!.
mysql -u usuario -p nombre_base_de_datos < archivorespaldo.sql
Y listo!!! con esto de volada a pasar la información, solo es cosa de subirla al server ya sea por FTP, o sFTP y luego entrar a la consola.
En la MacBook instalé el XAMPP y despues hice un script en PHP para ejecutarlo desde la consola, pero me arrojaba el siguiente error:
MDB2 Error: connect failed : connect: [Error message: Can’t connect to local MySQL server through socket ‘/var/mysql/mysql.sock’ (2)
Pues resulta que en mi configuración del MySQL en el servidor a conectarme manejaba localhost, pues resulta que ese era el error, como que el MacOSx no resuelve el nombre localhost, así que tenemos 2 opciones, cambiarlo por Localhost (así como ven!, con una L mayuscula) o poner el 127.0.0.1 y listo!!, sin errores!.
Lo que hace una letra es fatal!!…, pero lo bueno es que casi-siempre existen soluciones sencillas
, como dicen, para errores complicados, soluciones sencillas.
