2011-10-20 43 views
5

Tôi có một bảng trong cơ sở dữ liệu MySQL của tôi được gọi là 'trẻ em'. Trong bảng đó là một hàng được gọi là 'mong muốn' (một danh sách được phân cách bằng dấu phẩy của các mục trong danh sách yêu thích của trẻ). Tôi cần có thể cập nhật danh sách đó để nó chỉ xóa một giá trị. tức là danh sách = Kích thước 12 quần jean thông thường, ván lướt sóng, mũ bóng chày màu đỏ Sox; Tôi muốn loại bỏ Ván lướt sóng.Xóa các giá trị trong danh sách được phân tách bằng dấu phẩy khỏi cơ sở dữ liệu

truy vấn của tôi ngay bây giờ trông như thế này

$select = mysql_query('SELECT * FROM children WHERE caseNumber="'.$caseNum.'" LIMIT 1 '); 
    $row = mysql_fetch_array($select); 

    foreach ($wish as $w) { 
     $allWishes = $row['wishes']; 
     $newWishes = str_replace($w, '', $allWishes); 
     $update = mysql_query("UPDATE children SET wishes='$newWishes' WHERE caseNum='".$caseNum."'"); 
} 

Nhưng truy vấn UPDATE không loại bỏ bất cứ điều gì. Làm thế nào tôi có thể làm những gì tôi cần?

+5

Tôi nghĩ rằng những lời chúc nên bảng riêng của nó và liên kết trở lại đây bằng cách chia sẻ caseNumber then chốt. –

+0

Có vẻ thiếu một chuỗi nối nhưng một khi được sắp xếp, bạn sẽ để lại truy vấn này mở cho SQL Injection - một hacker sẽ thực sự có được những gì họ muốn. – Andrew

+0

@ Daren - thats thực sự là câu trả lời đúng, mô hình DB là sai và cần sửa chữa. Đáng tiếc, những người bình chọn trên các bình luận không đếm số – Andrew

Trả lời

3

Sử dụng these user-defined REGEXP_REPLACE() functions, bạn có thể thay thế nó bằng một chuỗi rỗng:

UPDATE children SET wishes = REGEXP_REPLACE(wishes, '(,(\s)?)?Surfboard', '') WHERE caseNum='whatever'; 

Thật không may, bạn không thể chỉ cần sử dụng đồng bằng cũ REPLACE() bởi vì bạn không biết được nơi trong chuỗi 'Lội' xuất hiện. Trong thực tế, các regex ở trên có lẽ sẽ cần thêm tinh chỉnh nếu 'Surfboard' xảy ra ở đầu hoặc cuối.

lẽ bạn có thể cắt bỏ đầu và đuôi dấu phẩy còn sót lại như thế này:

UPDATE children SET wishes = TRIM(BOTH ',' FROM REGEXP_REPLACE(wishes, '(,(\s)?)?Surfboard', '')) WHERE caseNum='whatever'; 

Vì vậy, những gì đang xảy ra ở đây? Regex loại bỏ 'Ván lướt sóng' cộng với dấu phẩy tùy chọn & trước đó. Sau đó, chức năng xung quanh TRIM() loại bỏ một dấu phẩy có thể có trong trường hợp 'Ván lướt sóng' xảy ra ở đầu chuỗi. Điều đó có lẽ cũng có thể được xử lý bởi regex, nhưng thẳng thắn, tôi quá mệt mỏi để giải quyết nó.

Lưu ý, Tôi chưa bao giờ sử dụng bản thân mình và không thể xác minh tính hiệu quả hoặc tính chắc chắn của nó, nhưng đó là nơi để bắt đầu. Và, như những người khác đang đề cập đến trong các ý kiến, bạn thực sự cần phải có trong một bảng danh sách mong muốn bình thường, chứ không phải là một chuỗi phân cách bằng dấu phẩy.

Cập nhật

Suy nghĩ về chi tiết này, tôi là một phần nhiều chỉ buộc việc sử dụng built-in REPLACE() và sau đó làm sạch các dấu phẩy, nơi bạn có thể nhận được hai dấu phẩy liên tiếp. Điều này đang tìm kiếm hai dấu phẩy cạnh nhau, như thể không có dấu cách nào ngăn cách các mục danh sách gốc của bạn. Nếu các mục đã được phân tách bằng dấu phẩy và dấu cách, hãy thay đổi ',,' thành ', ,' trong cuộc gọi bên ngoài REPLACE().

UPDATE children SET wishes = TRIM(BOTH ',' FROM REPLACE(REPLACE(wishes, 'Surfboard', ''), ',,', ',')) WHERE caseNum='whatever'; 
1

Không chính xác là câu trả lời trực tiếp cho câu hỏi của bạn, nhưng như Daren nói sẽ tốt hơn nếu bạn muốn làm bảng riêng. Có lẽ bạn có thể thay đổi sơ đồ cơ sở dữ liệu của bạn, do đó bạn có 3 bảng, ví dụ:

children 
-> caseNum 
-> childName 

wishes 
-> caseNum 
-> wishId 
-> wishName 

childrensWishes 
-> caseNum 
-> wishId 

Sau đó, để thêm hoặc xóa một mong muốn cho một đứa trẻ, bạn chỉ cần thêm hoặc xóa hàng có liên quan từ childrensWishes. Thiết kế hiện tại của bạn làm cho nó khó thao tác (như bạn đang tìm kiếm), cộng với lá bạn có nguy cơ dữ liệu không phù hợp.

Là câu trả lời trực tiếp hơn, bạn có thể sửa cách hiện tại của mình bằng cách lấy danh sách mong muốn, giải mã(), loại bỏ chúng mà bạn không muốn khỏi mảng và implode() 'đưa nó trở lại một chuỗi để cập nhật cơ sở dữ liệu.

0

Make muốn bảng có định dạng này:

caseNumber,wish 

Sau đó, bạn nhận được tất cả các mong muốn của một đứa trẻ như thế này:

SELECT * FROM children c left join wishes w on c.caseNumber = w.caseNumber WHERE c.caseNumber= ? 

Loại bỏ một mong muốn trở thành:

DELETE from wishes where caseNumber = ? 

Thêm một mong muốn trở thành:

INSERT into wishes (caseNumber,wish) values (?,?) 

Trở một điều ước trở thành:

SELECT * FROM children c left join wishes w on c.caseNumber = w.caseNumber WHERE c.caseNumber= ? LIMIT 1 
0

Có những lời chúc được lập chỉ mục trong một mảng mà sau đó đăng có thể là một ý tưởng, nếu không bạn sẽ cần phải lấy chuỗi, cắt nó, loại bỏ các phần bạn don' t muốn, sau đó nối các phần còn lại. Điều này có thể được thực hiện bằng cách sử dụng chức năng explode().

Nếu bạn đã sử dụng một mảng, bạn sẽ lấy lại mảng và sau đó sắp xếp thông qua nó với một vòng lặp như thế này:

// Wishes array: 
// Array (
//  [0] Regular Jeans 
//  [1] Surfboard 
//  [2] Red Sox Baseball Cap 
//) 

$wishes = $row['wishes']; // This is a serialized array taken from the database 
$wishes = unserialize($wishes); 

foreach ($wishes as $key => $value) { 
    if ($value == 'Surfboard') { 
     unset($wishes[$key]); 
     break; 
    } 
} 

$wishes = serialize($wishes); 
// Update database 

Hãy ghi nhớ rằng chỉ số [1] bây giờ sẽ không tồn tại trong mảng, vì vậy nếu bạn muốn có một mảng sạch bạn nên lặp qua mảng và làm cho nó tạo ra một mảng mới bằng cách riêng của mình:

foreach ($wishes as $wishes) { 
    $newArray[] = $wishes; 
} 
0

tôi nghĩ câu trả lời tốt nhất cho vấn đề như vậy là ở đây The best way to remove value from SET field?

truy vấn nên như thế này trong đó bao gồm, giá trị hoặc giá trị, hoặc giá trị duy nhất trong dấu phẩy tách cột

 
UPDATE yourtable 
SET 
    categories = 
    TRIM(BOTH ',' FROM 
     REPLACE(
     REPLACE(CONCAT(',',REPLACE(col, ',', ',,'), ','),',2,', ''), ',,', ',') 
    ) 
WHERE 
    FIND_IN_SET('2', categories) 

đây bạn có thể có điều kiện của bạn trong mệnh đề where. để biết thêm chi tiết, hãy tham khảo liên kết ở trên.

0

Bạn có thể tạo chức năng như thế này:

CREATE FUNCTION `remove_from_set`(v int,lst longtext) RETURNS longtext CHARSET utf8 
BEGIN 
set @lst=REPLACE(@lst, ',,', ','); 
set @lng=LENGTH(@lst) - LENGTH(REPLACE(@lst, ',', ''))+1; 
set @p=find_in_set(@v,@lst); 
set @l=SUBSTRING_INDEX(@lst, ',', @p-1); 
set @r=SUBSTRING_INDEX(@lst, ',', @[email protected]); 
IF @l!='' AND @r!='' THEN 
    return CONCAT(@l,',',@r); 
ELSE 
    RETURN CONCAT(@l,'',@r); 
END IF; 
END 

Sử dụng:

SELECT remove_from_set('1,,2,3,4,5,6',1) 
Các vấn đề liên quan