2009-02-17 12 views
5

Tengo dos tablas en una base de datos SQLite, INVITEM y SHOPITEM. Su atributo compartido es ItemId y quiero realizar una UNIÓN INTERNA. Aquí está la consulta:"nombre de columna ambigua" en SQLite INNER JOIN

SELECT INVITEM.CharId AS CharId, 
      INVITEM.ItemId AS ItemId 
     FROM (INVITEM as INVITEM 
INNER JOIN SHOPITEM AS SHOPITEM 
     ON SHOPITEM.ItemId = INVITEM.ItemId) 
    WHERE ItemId = 3; 

SQLite no le gusta:

SQL error: ambiguous column name: ItemId 

El error desaparece si escribo WHERE INVITEM.ItemId = 3, pero dado que la condición WHERE es más o menos especificado por el usuario, prefiero hacer funciona sin tener que especificar la tabla. NATURAL JOIN parece resolver el problema, pero no estoy seguro si la solución es lo suficientemente general (es decir, podría usarlo en este caso, pero no estoy seguro si puedo usarlo en todos los casos)

Cualquier SQL alternativo sintaxis que solucionaría el problema?

Respuesta

0

Me gustaría evitar que el usuario pueda escribir cláusulas SQL directamente. Esta es la fuente de las vulnerabilidades de inyección de SQL.

Si necesita que la consulta sea flexible, intente analizar la entrada del usuario y agregar la cláusula where correspondiente.

Aquí hay un código C# para mostrar la idea general

// from user input 
string user_column = "ItemID"; 
string user_value = "3"; 

string sql = "SELECT INVITEM.CharId AS CharId, INVITEM.ItemId AS ItemId FROM (INVITEM as INVITEM INNER JOIN SHOPITEM AS SHOPITEM ON SHOPITEM.ItemId = INVITEM.ItemId) "; 

if (user_column == "ItemID") 
{ 
    // using Int32.Parse here to prevent rubbish like "0 OR 1=1; --" being entered. 
    sql += string.Format("WHERE INVITEM.ItemID={0}",Int32.Parse(user_value)); 
} 

Obviamente, si usted está tratando con más de una cláusula, que tendría que sustituir Y por DONDE en las cláusulas siguientes.

+0

Terminé haciendo algo como esto. Nunca le permito al usuario escribir SQL directamente, pero las cláusulas WHERE se construyen usando plantillas de expresión. Calificar los nombres de las columnas cuando sea necesario fue suficiente. – ggambett

0

Simplemente cambie su alias de columna a algo similar, pero único (como ITEM_ID).

10

que iba a escribir esta consulta de esta manera:

SELECT i.CharId AS CharId, i.ItemId AS ItemId 
FROM INVITEM as i INNER JOIN SHOPITEM AS s USING (ItemId) 
WHERE i.ItemId = 3; 

estoy usando la sintaxis USING (ItemId) que es sólo una cuestión de gusto. Es equivalente a ON (i.ItemID = s.ItemID).

Pero resolví la ambigüedad calificando i.ItemID en la cláusula WHERE. Usted pensaría que esto no es necesario, ya que i.ItemID = s.ItemID. Ambos son iguales por conmutatividad, por lo que no hay ambigüedad semántica. Pero aparentemente SQLite no es lo suficientemente inteligente como para saber eso.

No me gusta usar NATURAL JOIN. Es equivalente a una combinación equitativa de cada columna que existe en ambas tablas con el mismo nombre. No me gusta usar esto porque no quiero que compare columnas que no quiero, simplemente porque tienen el mismo nombre.