通过传递表名称和列名称从Oracle表中删除行
我有jsp页面,其中用户选择表名称,列名称和列值,这三个条件我想从数据库中删除所有匹配的行。有没有办法在oracle中传递表名,列名和列值以从表中删除特定行?任何示例将帮助我。谢谢通过传递表名称和列名称从Oracle表中删除行
我担心SQL注入攻击,你提供的是表和列名。 您可以创建一个Oracle函数删除所需的记录,并删除该行之前必须满足的测试对于某些条件:
CREATE OR REPLACE
FUNCTION delete_record (
p_table IN VARCHAR2,
p_column IN VARCHAR2,
p_value IN VARCHAR2
)
RETURN NUMBER
AS
v_table user_tables.table_name%TYPE;
v_columns user_tab_cols.column_name%TYPE;
BEGIN
-- Check table exists in DB
SELECT table_name
INTO v_table
FROM user_tables
WHERE table_name = UPPER(p_table);
-- Check column exists in DB table
SELECT column_name
INTO v_colums
FROM user_tab_cols
WHERE table_name = UPPER(p_table)
AND column_name = UPPER(p_column);
EXECUTE IMMEDIATE
'DELETE FROM '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_table)||
' WHERE '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_column)||' = :col_value'
USING p_value;
RETURN SQL%ROWCOUNT;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
-- Either return -1 (error) or log an error etc.
RETURN -1;
WHEN others
THEN
<Your exception handling here>
END delete_record;
/
本(或像这样)会检查所提供的表和列变量的存在数据库,然后删除记录并返回删除的记录数。 如果删除的号码出现问题,您可以发出回滚语句,如果没有问题,则可以发出提交。
当然,如果您想提供完全限定的表名(建议),那么您将使用DBMS_ASSERT.QUALIFIED_SQL_NAME函数而不是DBMS_ASSERT.SIMPLE_SQL_NAME函数。
希望它可以帮助...
编辑:在回答杰克的有关从和日期添加日期的问题。
如果添加的是在传递给函数的两个新条件:
CREATE OR REPLACE
FUNCTION delete_record (
p_table IN VARCHAR2,
p_column IN VARCHAR2,
p_value IN VARCHAR2,
p_date_from IN DATE,
p_date_to IN DATE
)
然后,你需要扩大EXECUTE立即用:
EXECUTE IMMEDIATE
'DELETE FROM '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_table)||
' WHERE '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_column)||' = :col_value'||
' AND date BETWEEN :date_from AND :date_to'
USING p_value,
p_date_from,
p_date_to;
注:这假设你的日期列在表中称为“日期”。 我目前没有SQL界面在我面前,但这应该足够接近你需要的工作。
如果您将p_date_XXXX参数作为VARCHAR2而不是DATE类型传递,那么在将值传递给动态SQL之前,需要先“TO_DATE”。
例如
EXECUTE IMMEDIATE
'DELETE FROM '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_table)||
' WHERE '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_column)||' = :col_value'||
' AND date BETWEEN :date_from AND :date_to'
USING p_value,
TO_DATE(p_date_from, <date_format>),
TO_DATE(p_date_to, <date_format>);
我不确定这会停止sql注入:假设表名是“users”,列名是“id “并且是数字。如果我在p_value中传递以下内容会发生什么:“5 or 1 = 1”? 它会变成类似于:从用户id = 5或1 = 1删除 不会从数据库中删除所有用户吗? –
@ A.J。不,使用列值的绑定变量会阻止您声明的SQL注入。 (请参阅:http://download.oracle。COM /文档/ CD/B19306_01/appdev.102/b14251/adfns_dynamic_sql.htm#BJECFFHD)。但从根本上说,OP知道要传递给函数的是什么类型的值,并且使用这些特定的知识可以调整函数以加强它抵御潜在的威胁。理想情况下,没有数据库功能会使用动态SQL来完全保护,但不幸的是,这是一个乌托邦(以我的经验)很少发生。 – Ollie
谢谢我今天学到了东西:))))) –
DELETE FROM table_name WHERE column_name = column_value
的问题是,你不能在PreparedStatement
绑定表或列名,仅列值。
这应该工作(从内存中,未测试):
Statement stmt = null;
try
{
stmt = conn.createStatement("DELETE FROM " + tableName + " WHERE " + columnName + " = '" + condition + "'");
int deleted = stmt.execute();
}
catch (SQLException e)
{
... report error
}
try
{
if (stmt != null)
stmt.close();
}
catch (SQLException ignore)
{
}
您可能必须使用动态SQL,但在这种情况下要非常小心,以防止SQL注入,因为您正在传递的内容可能会导致严重的被劫持。 http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/dynamic.htm – Ollie