1

假设我有 3 个表,即,sales_order和设置 ON UPDATE = NO ACTION ON DELETE = NO ACTION。sales_order_itemsinvoice

现在我需要能够删除销售订单。但是,如果任何其他表中存在关系,则意味着该销售订单在其他地方使用,我需要防止删除。

例如:我有 sales_order_id = 34 ,我想检查它是否存在于任何其他表中。

以前为了实现同样的事情,我使用了事务,如下所示

$db = new database();

//start transaction

$db->start_trans();

//try to delete the sales order with ID = 34
$db->exec( 'DELETE FROM SALES_ORDER WHERE ID = 34' );

//check transaction success or failure 

if( $db->trans_status() == true ){

 //THERE IS NO RELATION EXISTS
 //ROLLBACK
 $db->rollback_trans();

 #Soft Delete the record     
 $db->exec( 'UPDATE sales_order SET is_deleted = 1 WHERE id = 34' );

}else{

 //RELATION EXISTS FOR ID = 34 IN SOME OTHER TABLES
}

上面的代码有效,但问题出在sales_order_items. 因为它是一个子表,sales_order如果它有内容,那么事务将失败并尝试执行 else 部分。

但实际上sales_order_items是一个属性,sales_order我需要删除那个特定的 sales_order (不关心项目)。

我期待这样的事情

$relations = $db->get_relation( 'sales_order.id', '34' );

预期产出

array( 'sales_order_items','invoice','another_table' .... );

注意:以上只是一个例子,我有很多表,不可能遍历每个表并检查是否ID 存在。

4

2 回答 2

2
select * from information_schema.table_constraints
where constraint_schema = DATABASE();

select * from information_schema.key_column_usage
where constraint_schema = DATABASE();

SQLFIDDLE

于 2013-07-24T06:33:37.763 回答
0

感谢 Revoua 提供了一个很好的答案。这是满足我需要的小修改版本。如果有更好的方法,请纠正我。

function check_relation( $table_name , $table_column ,$table_value ){

        //Get relation tables
        $qry = "SELECT  table_name,
                column_name,
                referenced_table_name,
                referenced_column_name 
                FROM information_schema.KEY_COLUMN_USAGE
                WHERE REFERENCED_TABLE_SCHEMA = ?
                AND REFERENCED_TABLE_NAME is not null
                AND referenced_table_name = ?
                AND referenced_column_name = ?";

        $db = $this->crm->db;

        //database name
        $database = $db->dbprefix.$db->database;

        //predefined array to store table names
        $related_tables = array();

        //execute the query 
        $qry = $db->query( $qry , array( $database , $table_name ,$table_column ) );

        unset($database);

        //Make sure that query is success
        if( $qry != FALSE && $qry->row_count() > 0 ){

            //Get as array
            $result = $qry->to_array();
            unset($qry);

            foreach( $result as $result_item ){

                //Get count based on table_value
                $qry = "SELECT COUNT(*)as total FROM ".$result_item['table_name']." WHERE ".$result_item['column_name']." = ? and is_del = 0";
                $qry = $db->query($qry,array($table_value));

                if( $qry!= FALSE && $qry->row_count() > 0 ) {

                    $qry = $qry->to_array(1);

                    //There are some entries ..
                    if( intval($qry['total']) > 0 ){        
                        $related_tables[] = $result_item['table_name'];
                    }

                }


            }

            return $related_tables;

        }else{
            return $related_tables;
        }

    }

用法:

$relation = $db->check_relation("SALES_ORDER","ID",34);

var_dump($关系)==>

array( 'SALES_ORDER_ITEM','INVOICE' ... );

现在在业务逻辑中

if( empty( $relation )  ){

  // No relation exists

}elseif( in_array( 'invoice', $relation ) ){

   $message->set_message("Cannot delete Sales Order, Invoice exists.");

}else ...
于 2013-07-24T08:34:45.357 回答