2012-11-14 25 views
8

Im tạo chương trình python kết nối với mysql.Cách kiểm tra xem bản ghi có tồn tại không bằng Python MySQdb

tôi cần phải kiểm tra xem một bảng chứa số 1 để chứng minh rằng nó đã kết nối thành công, đây là mã của tôi vậy, đến nay:

xcnx.execute('CREATE TABLE settings(status INT(1) NOT NULL)') 
    xcnx.execute('INSERT INTO settings(status) VALUES(1)') 
    cnx.commit() 
    sqlq = "SELECT * FROM settings WHERE status = '1'" 
    xcnx.execute(sqlq) 
    results = xcnx.fetchall() 
    if results =='1': 
    print 'yep its connected' 
    else: 
    print 'nope not connected' 

những gì đã tôi bị mất? Tôi là một noob sql, cảm ơn guys.

+0

Bạn chỉ muốn để kiểm tra xem bạn có thể tạo kết nối tới cơ sở dữ liệu hay bạn có thể tạo bảng và chèn dữ liệu thành công không? – jdi

+0

nope tôi biết tôi có thể kết nối tạo và chèn, tôi chỉ cần biết làm thế nào để kiểm tra và xác minh nếu một bản ghi tồn tại. –

Trả lời

14

Tôi tin rằng hiệu quả nhất "nó tồn tại" truy vấn chỉ là để làm một count:

sqlq = "SELECT COUNT(1) FROM settings WHERE status = '1'" 
xcnx.execute(sqlq) 
if xcnx.fetchone()[0]: 
    # exists 

Thay vì yêu cầu các cơ sở dữ liệu để thực hiện bất kỳ hoạt động đếm trên lĩnh vực hoặc các hàng, bạn chỉ yêu cầu nó trả về 1 hoặc 0 nếu kết quả tạo ra bất kỳ kết quả phù hợp nào. Điều này hiệu quả hơn nhiều khi trả lại các bản ghi thực tế và đếm số lượng phía máy khách vì nó tiết kiệm tuần tự hóa và deserialization ở cả hai bên và truyền dữ liệu.

In [22]: c.execute("select count(1) from settings where status = 1") 
Out[22]: 1L # rows 

In [23]: c.fetchone()[0] 
Out[23]: 1L # count found a match 

In [24]: c.execute("select count(1) from settings where status = 2") 
Out[24]: 1L # rows 

In [25]: c.fetchone()[0] 
Out[25]: 0L # count did not find a match 

count(*) sẽ giống như count(1). Trong trường hợp của bạn bởi vì bạn đang tạo một bảng mới, nó sẽ hiển thị 1 kết quả. Nếu bạn có 10.000 trận đấu, nó sẽ là 10000. Nhưng tất cả những gì bạn quan tâm trong bài kiểm tra của bạn là liệu nó có phải là 0 không, vì vậy bạn có thể thực hiện bài kiểm tra sự thật bool.

Cập nhật

Trên thực tế, nó thậm chí còn nhanh hơn để chỉ cần sử dụng rowcount, và thậm chí không lấy kết quả:

In [15]: if c.execute("select (1) from settings where status = 1 limit 1"): 
      print True 
True 

In [16]: if c.execute("select (1) from settings where status = 10 limit 1"): 
      print True 

In [17]: 

Đây cũng là cách ORM django của hiện một queryObject.exists().

+0

Tôi chắc chắn đồng ý với phương pháp của bạn và sẽ sử dụng nó trong mọi tình huống khác, nhưng tôi tin rằng 'COUNT (*)' là một trường hợp kỳ lạ khi một hàng thực sự được trả về ngay cả trong trường hợp không khớp (hàng chỉ chứa số 0). – RocketDonkey

+0

@RocketDonkey: Tôi vừa sửa ví dụ của mình để sử dụng chế độ tối thiểu nhất có thể để kiểm tra sự tồn tại của truy vấn. Làm một 'đếm (1)' thậm chí còn nhỏ hơn. Và bạn sẽ kiểm tra kết quả đầu tiên cho một int duy nhất. – jdi

+0

+1, bạn nhận được phiếu bầu của tôi :) – RocketDonkey

1

Khi bạn chạy results = xcnx.fetchall(), giá trị trả về là một chuỗi các bộ chứa chứa các giá trị hàng. Do đó khi bạn kiểm tra xem results == '1', bạn đang cố gắng so sánh một chuỗi với một hằng số, sẽ trả về False. Trong trường hợp của bạn, một hàng duy nhất có giá trị 0 sẽ được trả lại, vì vậy bạn có thể thử này:

results = xcnx.fetchall() 
# Get the value of the returned row, which will be 0 with a non-match 
if results[0][0]: 
    print 'yep its connected' 
else: 
    print 'nope not connected' 

Hoặc bạn có thể sử dụng một DictCursor (khi tạo con trỏ, sử dụng .cursor(MySQLdb.cursors.DictCursor) mà sẽ làm cho mọi việc một chút dễ dàng hơn để diễn giải mã, nhưng kết quả giống nhau:

if results[0]['COUNT(*)]': 
    # Continues... 

Ngoài ra, không phải là vấn đề lớn trong trường hợp này, nhưng bạn đang so sánh giá trị số nguyên với chuỗi. MySQL sẽ thực hiện chuyển đổi kiểu, nhưng bạn có thể sử dụng SELECT COUNT(*) FROM settings WHERE status = 1 và lưu một chút (rất nhỏ) xử lý.

2

Nếu tất cả những gì bạn muốn làm là kiểm tra xem bạn đã thiết lập thành công kết nối thì tại sao bạn đang cố gắng tạo bảng, chèn hàng và sau đó truy xuất dữ liệu từ đó?

Bạn chỉ có thể làm như sau ...

sqlq = "SELECT * FROM settings WHERE status = '1'" 
xcnx.execute(sqlq) 
results = xcnx.fetchone() 
if results =='1': 
    print 'yep its connected' 
else: 
    print 'nope not connected' 

Trong thực tế, nếu chương trình của bạn đã không ném một ngoại lệ cho đến nay chỉ ra rằng bạn đã thiết lập kết nối thành công. (Do kiểm tra mã trên, tôi không chắc chắn nếu fetchone sẽ trả về một tuple, string, hoặc int trong trường hợp này).

Nhân tiện, nếu vì lý do nào đó bạn cần tạo bảng, tôi khuyên bạn nên bỏ bảng này trước khi bạn thoát để chương trình của bạn chạy thành công lần thứ hai.

0

Gần đây tôi đã cải thiện hiệu quả của mình bằng cách thay vì truy vấn chọn, chỉ cần thêm chỉ mục chính vào cột duy nhất và sau đó thêm nó. MySQL sẽ chỉ thêm nó nếu nó không tồn tại.

Vì vậy, thay vì 2 báo cáo:

Query MySQL for exists: 
    Query MySQL insert data 

Chỉ cần 1 và nó sẽ chỉ làm việc nếu nó là duy nhất:

Query MySQL insert data 

1 Query là tốt hơn so với 2.

Các vấn đề liên quan