Java 通过传递表名和列名从Oracle表中删除行

Java 通过传递表名和列名从Oracle表中删除行,java,sql,oracle,Java,Sql,Oracle,我有一个jsp页面,用户在其中选择表名、列名和列值,根据这三个条件,我希望从数据库中删除所有匹配的行。有没有一种方法可以在oracle中传递表名、列名和列值以从表中删除某些行?任何例子都会对我有帮助。。多谢各位 DELETE FROM table_name WHERE column_name = column_value 问题是无法在PreparedStatement中绑定表名或列名,只能绑定列值。这应该可以工作(从内存;未测试): 在提供表名和列名时,我会担心SQL注入攻击。 您可以创建一个

我有一个jsp页面,用户在其中选择表名、列名和列值,根据这三个条件,我希望从数据库中删除所有匹配的行。有没有一种方法可以在oracle中传递表名、列名和列值以从表中删除某些行?任何例子都会对我有帮助。。多谢各位

DELETE FROM table_name WHERE column_name = column_value
问题是无法在
PreparedStatement
中绑定表名或列名,只能绑定列值。

这应该可以工作(从内存;未测试):


在提供表名和列名时,我会担心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;
/
然后,您需要使用以下命令展开“立即执行”:

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而不是日期类型传递,那么在将其传递到动态SQL之前,您需要“to_date”这些值

e、 g

立即执行
'DELETE FROM'| | DBMS_ASSERT.SIMPLE_SQL_NAME(p_表)||
'其中'| | DBMS_ASSERT.SIMPLE_SQL_NAME(p|u列)|'=:col|u value'||
'和日期介于:date\u from和:date\u to'
使用p_值,
截止日期(自年月日起),
截止日期(p_DATE_TO,);

您可能必须使用动态SQL,但在这种情况下要非常小心,以防SQL注入,因为如果被劫持,您正在传递的内容可能会造成严重破坏。我不确定这是否会停止sql注入:假设表名为“users”,列名为“id”,并且是数字。如果我在p_值中传递下列值:“5或1=1”,会发生什么?它将变成这样:delete from users,其中id=5或1=1。这不会从数据库中删除所有用户吗?@A.J.不会,在您断言的情况下,使用bind变量作为列值会阻止SQL注入。(见:)。但从根本上说,OP知道将向函数传递什么类型的值,并且使用这些特定的知识可以定制函数以增强其抵御潜在威胁的能力。理想情况下,没有数据库功能会使用动态SQL进行完全保护,但不幸的是,这是一个乌托邦(以我的经验)很少发生。@Ollie我又添加了两个日期值条件,但它不起作用。你能告诉我我在这里做错了什么吗声明它像这个p|u date|u from IN date p|u date|u to IN date并将它添加到这里的查询中,它的abt date变量立即执行'DELETE from'| DBMS|u ASSERT.SIMPLE|u SQL|u NAME(p|u table)| WHERE'| DBMS|u ASSERT.SIMPLE|u SQL|u NAME(p|column)| coll|u value)使用p|u值,日期介于至日期(“起始日期”、“年月日”)和至日期(“起始日期”、“年月日”)之间@杰克。不能在绑定变量中提供SQL DML文本(防止SQL注入)。您需要扩展整个“executeimmediate”语句以适应新的条件。我将用一个新的部分来编辑我的答案,向你展示我的意思。
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 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;
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>);