OOP is probably more about an object's purpose and the structure of object/class relationships, than how an individual class is written. More importantly though, OOP is only useful when there's a problem that need solving. You haven't told us what the problem is this class aims to provide a solution for, so that's going to make it difficult to critique.
First of all though, as you suspected, those properties should be set to protected. Allowing anyone to modify those values directly opens up a whole can of worms. Using a setter, like you already have for setting the table, is almost always a safer option, as by using a setter, you can ensure that the set value of a valid type, format and value, and can then safely use that property in the rest of your class, resting assured that you won't encounter something unexpected. I generally only use public properties for allowing boolean values to be set, bit it really depends on the circumstances.
Just a note also (in case you had doubts around when to use 'protected' and 'private), you should only declare methods and properties as 'private' if you intend for your class to be sub-classed, and have a specific reason to hide those methods and properties from the inheriting class. Those cases are rare, so if in doubt, use 'protected' instead of 'private' to hide the implementation details of your class, from the rest of your application.
Another thing, why are you returning the table name from setTable()? I would return either a boolean (e.g. true) or nothing at all; in this case, I return nothing at all seeing as though setting a table will always succeed.
Generally speaking, this class doesn't showcase very good object-orientated design. The worker methods, select(), insert() and where() are just string builders which don't really interact with the rest of the class at all, or any other object for that matter. You could easily break apart these methods into procedural functions by just adding an additional argument to allow one to specify the table - something which strongly indicates poor OO design.
The truth is though, you can't have possibly demonstrated a good design, as your example serves no purpose. It doesn't solve any problem. It's just code for the sake of code. If you had said "Here's my class which I plan to use to talk to my database in my next project. I'm hoping it will make doing X easier.", then I'd be able to point out a whole load of issues with your class, and would be able to offer alternative solutions. But because this class isn't solving any particular problem (at least not that you'd told us) we can't possibly determine how well it has been designed.
So the thing you need to take away from this, is that before you cut any code, make sure you clearly understand the problem you're solving. It's the only way you can achieve a satisfactory outcome.